f2fs: make BG GC more aggressive for zoned devices
authorDaeho Jeong <daehojeong@google.com>
Mon, 9 Sep 2024 22:19:40 +0000 (15:19 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 11 Sep 2024 03:32:44 +0000 (03:32 +0000)
Since we don't have any GC on device side for zoned devices, need more
aggressive BG GC. So, tune the parameters for that.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/gc.c
fs/f2fs/gc.h
fs/f2fs/super.c

index 0abb7bb39296bdfd55d17aac401a7695c931c725..5031e7fa287a02078086ba496fc1f6381c1f303d 100644 (file)
@@ -2879,13 +2879,26 @@ static inline bool is_inflight_io(struct f2fs_sb_info *sbi, int type)
        return false;
 }
 
+static inline bool is_inflight_read_io(struct f2fs_sb_info *sbi)
+{
+       return get_pages(sbi, F2FS_RD_DATA) || get_pages(sbi, F2FS_DIO_READ);
+}
+
 static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
 {
+       bool zoned_gc = (type == GC_TIME &&
+                       F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_BLKZONED));
+
        if (sbi->gc_mode == GC_URGENT_HIGH)
                return true;
 
-       if (is_inflight_io(sbi, type))
-               return false;
+       if (zoned_gc) {
+               if (is_inflight_read_io(sbi))
+                       return false;
+       } else {
+               if (is_inflight_io(sbi, type))
+                       return false;
+       }
 
        if (sbi->gc_mode == GC_URGENT_MID)
                return true;
@@ -2894,6 +2907,9 @@ static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
                        (type == DISCARD_TIME || type == GC_TIME))
                return true;
 
+       if (zoned_gc)
+               return true;
+
        return f2fs_time_over(sbi, type);
 }
 
index 724bbcb447d32e731aa9ea35dd4e9ba2e2c29602..46e3bc26b78a629a9f214bb662757e3e531240b6 100644 (file)
@@ -116,7 +116,17 @@ static int gc_thread_func(void *data)
                        goto next;
                }
 
-               if (has_enough_invalid_blocks(sbi))
+               if (f2fs_sb_has_blkzoned(sbi)) {
+                       if (has_enough_free_blocks(sbi, LIMIT_NO_ZONED_GC)) {
+                               wait_ms = gc_th->no_gc_sleep_time;
+                               f2fs_up_write(&sbi->gc_lock);
+                               goto next;
+                       }
+                       if (wait_ms == gc_th->no_gc_sleep_time)
+                               wait_ms = gc_th->max_sleep_time;
+               }
+
+               if (need_to_boost_gc(sbi))
                        decrease_sleep_time(gc_th, &wait_ms);
                else
                        increase_sleep_time(gc_th, &wait_ms);
@@ -179,9 +189,16 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
                return -ENOMEM;
 
        gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME;
-       gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME;
-       gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
-       gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
+
+       if (f2fs_sb_has_blkzoned(sbi)) {
+               gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME_ZONED;
+               gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME_ZONED;
+               gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME_ZONED;
+       } else {
+               gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME;
+               gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
+               gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
+       }
 
        gc_th->gc_wake = false;
 
index a8ea3301b815ad4f3cbce63775afc033fecf1642..55c4ba73362ef96d8c1e90e478b5cc62fcec107a 100644 (file)
 #define DEF_GC_THREAD_MAX_SLEEP_TIME   60000
 #define DEF_GC_THREAD_NOGC_SLEEP_TIME  300000  /* wait 5 min */
 
+/* GC sleep parameters for zoned deivces */
+#define DEF_GC_THREAD_MIN_SLEEP_TIME_ZONED     10
+#define DEF_GC_THREAD_MAX_SLEEP_TIME_ZONED     20
+#define DEF_GC_THREAD_NOGC_SLEEP_TIME_ZONED    60000
+
 /* choose candidates from sections which has age of more than 7 days */
 #define DEF_GC_THREAD_AGE_THRESHOLD            (60 * 60 * 24 * 7)
 #define DEF_GC_THREAD_CANDIDATE_RATIO          20      /* select 20% oldest sections as candidates */
@@ -25,6 +30,9 @@
 #define LIMIT_INVALID_BLOCK    40 /* percentage over total user space */
 #define LIMIT_FREE_BLOCK       40 /* percentage over invalid + free space */
 
+#define LIMIT_NO_ZONED_GC      60 /* percentage over total user space of no gc for zoned devices */
+#define LIMIT_BOOST_ZONED_GC   25 /* percentage over total user space of boosted gc for zoned devices */
+
 #define DEF_GC_FAILED_PINNED_FILES     2048
 #define MAX_GC_FAILED_PINNED_FILES     USHRT_MAX
 
@@ -152,6 +160,12 @@ static inline void decrease_sleep_time(struct f2fs_gc_kthread *gc_th,
                *wait -= min_time;
 }
 
+static inline bool has_enough_free_blocks(struct f2fs_sb_info *sbi,
+                                               unsigned int limit_perc)
+{
+       return free_sections(sbi) > ((sbi->total_sections * limit_perc) / 100);
+}
+
 static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
 {
        block_t user_block_count = sbi->user_block_count;
@@ -167,3 +181,10 @@ static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
                free_user_blocks(sbi) <
                        limit_free_user_blocks(invalid_user_blocks));
 }
+
+static inline bool need_to_boost_gc(struct f2fs_sb_info *sbi)
+{
+       if (f2fs_sb_has_blkzoned(sbi))
+               return !has_enough_free_blocks(sbi, LIMIT_BOOST_ZONED_GC);
+       return has_enough_invalid_blocks(sbi);
+}
index 1c9316788a16106c8f8d2338a8dcff26cebea47a..69aee4c3d97f6fe6c7c22df484a63d60f4ee97e5 100644 (file)
@@ -706,6 +706,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
                        if (!strcmp(name, "on")) {
                                F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
                        } else if (!strcmp(name, "off")) {
+                               if (f2fs_sb_has_blkzoned(sbi)) {
+                                       f2fs_warn(sbi, "zoned devices need bggc");
+                                       kfree(name);
+                                       return -EINVAL;
+                               }
                                F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_OFF;
                        } else if (!strcmp(name, "sync")) {
                                F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC;