2022-06-14 11:56:11

by qixiaoyu1

[permalink] [raw]
Subject: [PATCH 2/2] f2fs-tools: fix to check free space before grow

Otherwise, after grow, kernel may report below error message
when we mount the image if -o parameter is specified during resize:

F2FS-fs (loop0): invalid crc_offset: 0
F2FS-fs (loop0): Wrong valid_user_blocks: 16404, user_block_count: 13312
F2FS-fs (loop0): Failed to get valid F2FS checkpoint
mount(2) system call failed: Structure needs cleaning.

Signed-off-by: qixiaoyu1 <[email protected]>
---
fsck/resize.c | 36 ++++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/fsck/resize.c b/fsck/resize.c
index d19c6fa..e135b66 100644
--- a/fsck/resize.c
+++ b/fsck/resize.c
@@ -599,6 +599,26 @@ static void rebuild_checkpoint(struct f2fs_sb_info *sbi,
DBG(0, "Info: Done to rebuild checkpoint blocks\n");
}

+static int f2fs_resize_check(struct f2fs_sb_info *sbi, struct f2fs_super_block *new_sb)
+{
+ struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
+ block_t user_block_count;
+ unsigned int overprov_segment_count;
+
+ overprov_segment_count = (get_newsb(segment_count_main) -
+ c.new_reserved_segments) *
+ c.new_overprovision / 100;
+ overprov_segment_count += c.new_reserved_segments;
+
+ user_block_count = (get_newsb(segment_count_main) -
+ overprov_segment_count) * c.blks_per_seg;
+
+ if (get_cp(valid_block_count) > user_block_count)
+ return -1;
+
+ return 0;
+}
+
static int f2fs_resize_grow(struct f2fs_sb_info *sbi)
{
struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
@@ -616,6 +636,9 @@ static int f2fs_resize_grow(struct f2fs_sb_info *sbi)
if (get_new_sb(new_sb))
return -1;

+ if (f2fs_resize_check(sbi, new_sb) < 0)
+ return -1;
+
/* check nat availability */
if (get_sb(segment_count_nat) > get_newsb(segment_count_nat)) {
err = shrink_nats(sbi, new_sb);
@@ -659,11 +682,8 @@ static int f2fs_resize_shrink(struct f2fs_sb_info *sbi)
struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
struct f2fs_super_block new_sb_raw;
struct f2fs_super_block *new_sb = &new_sb_raw;
- struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
block_t old_end_blkaddr, old_main_blkaddr;
block_t new_end_blkaddr, new_main_blkaddr, tmp_end_blkaddr;
- block_t user_block_count;
- unsigned int overprov_segment_count;
unsigned int offset;
int err = -1;

@@ -674,15 +694,7 @@ static int f2fs_resize_shrink(struct f2fs_sb_info *sbi)
if (get_new_sb(new_sb))
return -1;

- overprov_segment_count = (get_newsb(segment_count_main) -
- c.new_reserved_segments) *
- c.new_overprovision / 100;
- overprov_segment_count += c.new_reserved_segments;
-
- user_block_count = (get_newsb(segment_count_main) -
- overprov_segment_count) * c.blks_per_seg;
-
- if (get_cp(valid_block_count) > user_block_count)
+ if (f2fs_resize_check(sbi, new_sb) < 0)
return -1;

/* check nat availability */
--
2.36.1


2022-06-19 00:32:28

by Chao Yu

[permalink] [raw]
Subject: Re: [PATCH 2/2] f2fs-tools: fix to check free space before grow

On 2022/6/14 19:49, qixiaoyu1 wrote:
> Otherwise, after grow, kernel may report below error message
> when we mount the image if -o parameter is specified during resize:
>
> F2FS-fs (loop0): invalid crc_offset: 0
> F2FS-fs (loop0): Wrong valid_user_blocks: 16404, user_block_count: 13312
> F2FS-fs (loop0): Failed to get valid F2FS checkpoint
> mount(2) system call failed: Structure needs cleaning.
>
> Signed-off-by: qixiaoyu1 <[email protected]>

It looks this patch should be merged into previous one, otherwise
-o option support is broken for resize.f2fs.

Thanks,

> ---
> fsck/resize.c | 36 ++++++++++++++++++++++++------------
> 1 file changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/fsck/resize.c b/fsck/resize.c
> index d19c6fa..e135b66 100644
> --- a/fsck/resize.c
> +++ b/fsck/resize.c
> @@ -599,6 +599,26 @@ static void rebuild_checkpoint(struct f2fs_sb_info *sbi,
> DBG(0, "Info: Done to rebuild checkpoint blocks\n");
> }
>
> +static int f2fs_resize_check(struct f2fs_sb_info *sbi, struct f2fs_super_block *new_sb)
> +{
> + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
> + block_t user_block_count;
> + unsigned int overprov_segment_count;
> +
> + overprov_segment_count = (get_newsb(segment_count_main) -
> + c.new_reserved_segments) *
> + c.new_overprovision / 100;
> + overprov_segment_count += c.new_reserved_segments;
> +
> + user_block_count = (get_newsb(segment_count_main) -
> + overprov_segment_count) * c.blks_per_seg;
> +
> + if (get_cp(valid_block_count) > user_block_count)
> + return -1;
> +
> + return 0;
> +}
> +
> static int f2fs_resize_grow(struct f2fs_sb_info *sbi)
> {
> struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
> @@ -616,6 +636,9 @@ static int f2fs_resize_grow(struct f2fs_sb_info *sbi)
> if (get_new_sb(new_sb))
> return -1;
>
> + if (f2fs_resize_check(sbi, new_sb) < 0)
> + return -1;
> +
> /* check nat availability */
> if (get_sb(segment_count_nat) > get_newsb(segment_count_nat)) {
> err = shrink_nats(sbi, new_sb);
> @@ -659,11 +682,8 @@ static int f2fs_resize_shrink(struct f2fs_sb_info *sbi)
> struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
> struct f2fs_super_block new_sb_raw;
> struct f2fs_super_block *new_sb = &new_sb_raw;
> - struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
> block_t old_end_blkaddr, old_main_blkaddr;
> block_t new_end_blkaddr, new_main_blkaddr, tmp_end_blkaddr;
> - block_t user_block_count;
> - unsigned int overprov_segment_count;
> unsigned int offset;
> int err = -1;
>
> @@ -674,15 +694,7 @@ static int f2fs_resize_shrink(struct f2fs_sb_info *sbi)
> if (get_new_sb(new_sb))
> return -1;
>
> - overprov_segment_count = (get_newsb(segment_count_main) -
> - c.new_reserved_segments) *
> - c.new_overprovision / 100;
> - overprov_segment_count += c.new_reserved_segments;
> -
> - user_block_count = (get_newsb(segment_count_main) -
> - overprov_segment_count) * c.blks_per_seg;
> -
> - if (get_cp(valid_block_count) > user_block_count)
> + if (f2fs_resize_check(sbi, new_sb) < 0)
> return -1;
>
> /* check nat availability */