diff options
author | Chao Yu <yuchao0@huawei.com> | 2019-05-16 20:40:43 +0800 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2019-05-20 17:42:52 -0700 |
commit | 54244dcafddcf87355b5515b60ea084ddb47e2d0 (patch) | |
tree | 7496024a7cf9fa82471d3fc0eedcbb28a78504ac | |
parent | 9e0a58749de8b62932388cfb645ee6248cd1b413 (diff) | |
download | f2fs-tools-54244dcafddcf87355b5515b60ea084ddb47e2d0.tar.gz |
fsck.f2fs: update curseg .next_blkoff/.alloc_type preferential
If .next_blkoff is inconsistent, we can update curseg .next_blkoff
to first unused block address, and change .alloc_type to SSR
preferential, instead of move curseg to other position.
This can help to repair fuzzed image which has no more free segment.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fsck/fsck.c | 23 | ||||
-rw-r--r-- | fsck/fsck.h | 1 | ||||
-rw-r--r-- | fsck/mount.c | 31 |
3 files changed, 50 insertions, 5 deletions
diff --git a/fsck/fsck.c b/fsck/fsck.c index 247b75e..6f0f262 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -2164,6 +2164,23 @@ int check_curseg_offsets(struct f2fs_sb_info *sbi) return 0; } +static void fix_curseg_info(struct f2fs_sb_info *sbi) +{ + int i, need_update = 0; + + for (i = 0; i < NO_CHECK_TYPE; i++) { + if (check_curseg_offset(sbi, i)) { + update_curseg_info(sbi, i); + need_update = 1; + } + } + + if (need_update) { + write_curseg_info(sbi); + flush_curseg_sit_entries(sbi); + } +} + int check_sit_types(struct f2fs_sb_info *sbi) { unsigned int i; @@ -2752,11 +2769,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) fix_hard_links(sbi); fix_nat_entries(sbi); rewrite_sit_area_bitmap(sbi); - if (check_curseg_offsets(sbi)) { - move_curseg_info(sbi, SM_I(sbi)->main_blkaddr, 0); - write_curseg_info(sbi); - flush_curseg_sit_entries(sbi); - } + fix_curseg_info(sbi); fix_checksum(sbi); fix_checkpoint(sbi); } else if (is_set_ckpt_flags(cp, CP_FSCK_FLAG) || diff --git a/fsck/fsck.h b/fsck/fsck.h index c56e733..f00036e 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -185,6 +185,7 @@ extern void f2fs_do_umount(struct f2fs_sb_info *); extern int f2fs_sparse_initialize_meta(struct f2fs_sb_info *); extern void flush_journal_entries(struct f2fs_sb_info *); +extern void update_curseg_info(struct f2fs_sb_info *, int); extern void zero_journal_entries(struct f2fs_sb_info *); extern void flush_sit_entries(struct f2fs_sb_info *); extern void move_curseg_info(struct f2fs_sb_info *, u64, int); diff --git a/fsck/mount.c b/fsck/mount.c index 21d71d4..aecd0cd 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -2159,6 +2159,30 @@ void flush_sit_entries(struct f2fs_sb_info *sbi) free(sit_blk); } +int relocate_curseg_offset(struct f2fs_sb_info *sbi, int type) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + struct seg_entry *se = get_seg_entry(sbi, curseg->segno); + unsigned int i; + + for (i = 0; i < sbi->blocks_per_seg; i++) { + if (!f2fs_test_bit(i, (const char *)se->cur_valid_map)) + break; + } + + if (i == sbi->blocks_per_seg) + return -EINVAL; + + DBG(1, "Update curseg[%d].next_blkoff %u -> %u, alloc_type %s -> SSR\n", + type, curseg->next_blkoff, i, + curseg->alloc_type == LFS ? "LFS" : "SSR"); + + curseg->next_blkoff = i; + curseg->alloc_type = SSR; + + return 0; +} + int find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, int type) { struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); @@ -2255,6 +2279,13 @@ void move_curseg_info(struct f2fs_sb_info *sbi, u64 from, int left) } } +void update_curseg_info(struct f2fs_sb_info *sbi, int type) +{ + if (!relocate_curseg_offset(sbi, type)) + return; + move_curseg_info(sbi, SM_I(sbi)->main_blkaddr, 0); +} + void zero_journal_entries(struct f2fs_sb_info *sbi) { int i; |