diff options
author | Chao Yu <yuchao0@huawei.com> | 2021-04-06 09:31:38 +0800 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2021-04-12 11:21:15 -0700 |
commit | 5263ae25fbab9fb1f253a107f4e745a574cd2140 (patch) | |
tree | e3509e92c5b85d221877933086627a635917f6f2 | |
parent | 159752dd3c97290bd10fe6433d8c7731f04a82dc (diff) | |
download | f2fs-tools-5263ae25fbab9fb1f253a107f4e745a574cd2140.tar.gz |
resize.f2fs: fix to check free space before shrink
Otherwise, after shrink, kernel will report below error message
when we mount the image:
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.
Reported-and-tested-by: beroal <me@beroal.in.ua>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fsck/resize.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/fsck/resize.c b/fsck/resize.c index a083f68..b043cd9 100644 --- a/fsck/resize.c +++ b/fsck/resize.c @@ -650,8 +650,11 @@ 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; @@ -662,6 +665,17 @@ 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) + return -1; + /* check nat availability */ if (get_sb(segment_count_nat) > get_newsb(segment_count_nat)) { err = shrink_nats(sbi, new_sb); |