f2fs: Fix over-estimating free section during FG GC
authorYonggil Song <yonggil.song@samsung.com>
Fri, 12 May 2023 04:16:10 +0000 (13:16 +0900)
committerJaegeuk Kim <jaegeuk@kernel.org>
Mon, 12 Jun 2023 20:04:07 +0000 (13:04 -0700)
There was a bug that finishing FG GC unconditionally because free sections
are over-estimated after checkpoint in FG GC.
This patch initializes sec_freed by every checkpoint in FG GC.

Signed-off-by: Yonggil Song <yonggil.song@samsung.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/gc.c

index d455140322a85f05491edda7c5fe9fa18b5e88fd..51d7e8d29bf182343a2bb8b7f3692f5da843910a 100644 (file)
@@ -1797,7 +1797,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control)
 {
        int gc_type = gc_control->init_gc_type;
        unsigned int segno = gc_control->victim_segno;
-       int sec_freed = 0, seg_freed = 0, total_freed = 0;
+       int sec_freed = 0, seg_freed = 0, total_freed = 0, total_sec_freed = 0;
        int ret = 0;
        struct cp_control cpc;
        struct gc_inode_list gc_list = {
@@ -1842,6 +1842,8 @@ gc_more:
                        ret = f2fs_write_checkpoint(sbi, &cpc);
                        if (ret)
                                goto stop;
+                       /* Reset due to checkpoint */
+                       sec_freed = 0;
                }
        }
 
@@ -1866,15 +1868,17 @@ retry:
                                gc_control->should_migrate_blocks);
        total_freed += seg_freed;
 
-       if (seg_freed == f2fs_usable_segs_in_sec(sbi, segno))
+       if (seg_freed == f2fs_usable_segs_in_sec(sbi, segno)) {
                sec_freed++;
+               total_sec_freed++;
+       }
 
        if (gc_type == FG_GC) {
                sbi->cur_victim_sec = NULL_SEGNO;
 
                if (has_enough_free_secs(sbi, sec_freed, 0)) {
                        if (!gc_control->no_bg_gc &&
-                           sec_freed < gc_control->nr_free_secs)
+                           total_sec_freed < gc_control->nr_free_secs)
                                goto go_gc_more;
                        goto stop;
                }
@@ -1901,6 +1905,8 @@ retry:
                ret = f2fs_write_checkpoint(sbi, &cpc);
                if (ret)
                        goto stop;
+               /* Reset due to checkpoint */
+               sec_freed = 0;
        }
 go_gc_more:
        segno = NULL_SEGNO;
@@ -1913,7 +1919,7 @@ stop:
        if (gc_type == FG_GC)
                f2fs_unpin_all_sections(sbi, true);
 
-       trace_f2fs_gc_end(sbi->sb, ret, total_freed, sec_freed,
+       trace_f2fs_gc_end(sbi->sb, ret, total_freed, total_sec_freed,
                                get_pages(sbi, F2FS_DIRTY_NODES),
                                get_pages(sbi, F2FS_DIRTY_DENTS),
                                get_pages(sbi, F2FS_DIRTY_IMETA),
@@ -1927,7 +1933,7 @@ stop:
        put_gc_inode(&gc_list);
 
        if (gc_control->err_gc_skipped && !ret)
-               ret = sec_freed ? 0 : -EAGAIN;
+               ret = total_sec_freed ? 0 : -EAGAIN;
        return ret;
 }