When fsck updates one of the current segments, update_curseg_info() is called specifying a single current segment as its argument. However, update_curseg_info() calls move_curseg_info() function which updates all six current segments. Then update_curseg_info() for a single current segment moves all current segments.
This excessive current segment move causes an issue when a new zone is assigned to a current segment because of write pointer inconsistency. Even when a current segment has write pointer inconsistency, all other current segments should not be moved because they may have fsync data at their positions. To avoid the excessive current segment move, introduce move_one_curseg_info() function which does same work as move_curseg_info() only for a single current segment. Call move_one_curseg_info() in place of move_curseg_info() from update_curseg_info(). Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawas...@wdc.com> Reviewed-by: Chao Yu <yuch...@huawei.com> Signed-off-by: Jaegeuk Kim <jaeg...@kernel.org> --- fsck/mount.c | 68 ++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/fsck/mount.c b/fsck/mount.c index 7ce885c..cd6b51b 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -2548,52 +2548,58 @@ int find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, return -1; } -void move_curseg_info(struct f2fs_sb_info *sbi, u64 from, int left) +static void move_one_curseg_info(struct f2fs_sb_info *sbi, u64 from, int left, + int i) { - int i, ret; + struct curseg_info *curseg = CURSEG_I(sbi, i); + struct f2fs_summary_block buf; + u32 old_segno; + u64 ssa_blk, to; + int ret; - /* update summary blocks having nullified journal entries */ - for (i = 0; i < NO_CHECK_TYPE; i++) { - struct curseg_info *curseg = CURSEG_I(sbi, i); - struct f2fs_summary_block buf; - u32 old_segno; - u64 ssa_blk, to; + /* update original SSA too */ + ssa_blk = GET_SUM_BLKADDR(sbi, curseg->segno); + ret = dev_write_block(curseg->sum_blk, ssa_blk); + ASSERT(ret >= 0); - /* update original SSA too */ - ssa_blk = GET_SUM_BLKADDR(sbi, curseg->segno); - ret = dev_write_block(curseg->sum_blk, ssa_blk); - ASSERT(ret >= 0); + to = from; + ret = find_next_free_block(sbi, &to, left, i, + c.zoned_model == F2FS_ZONED_HM); + ASSERT(ret == 0); - to = from; - ret = find_next_free_block(sbi, &to, left, i, - c.zoned_model == F2FS_ZONED_HM); - ASSERT(ret == 0); + old_segno = curseg->segno; + curseg->segno = GET_SEGNO(sbi, to); + curseg->next_blkoff = OFFSET_IN_SEG(sbi, to); + curseg->alloc_type = c.zoned_model == F2FS_ZONED_HM ? LFS : SSR; - old_segno = curseg->segno; - curseg->segno = GET_SEGNO(sbi, to); - curseg->next_blkoff = OFFSET_IN_SEG(sbi, to); - curseg->alloc_type = c.zoned_model == F2FS_ZONED_HM ? LFS : SSR; + /* update new segno */ + ssa_blk = GET_SUM_BLKADDR(sbi, curseg->segno); + ret = dev_read_block(&buf, ssa_blk); + ASSERT(ret >= 0); - /* update new segno */ - ssa_blk = GET_SUM_BLKADDR(sbi, curseg->segno); - ret = dev_read_block(&buf, ssa_blk); - ASSERT(ret >= 0); + memcpy(curseg->sum_blk, &buf, SUM_ENTRIES_SIZE); - memcpy(curseg->sum_blk, &buf, SUM_ENTRIES_SIZE); + /* update se->types */ + reset_curseg(sbi, i); - /* update se->types */ - reset_curseg(sbi, i); + FIX_MSG("Move curseg[%d] %x -> %x after %"PRIx64"\n", + i, old_segno, curseg->segno, from); +} - DBG(1, "Move curseg[%d] %x -> %x after %"PRIx64"\n", - i, old_segno, curseg->segno, from); - } +void move_curseg_info(struct f2fs_sb_info *sbi, u64 from, int left) +{ + int i; + + /* update summary blocks having nullified journal entries */ + for (i = 0; i < NO_CHECK_TYPE; i++) + move_one_curseg_info(sbi, from, left, i); } 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); + move_one_curseg_info(sbi, SM_I(sbi)->main_blkaddr, 0, type); } void zero_journal_entries(struct f2fs_sb_info *sbi) -- 2.23.0 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel