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

Reply via email to