f2fs: add GC_URGENT_LOW mode in gc_urgent
authorDaeho Jeong <daehojeong@google.com>
Thu, 2 Jul 2020 04:14:14 +0000 (13:14 +0900)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 8 Jul 2020 04:51:49 +0000 (21:51 -0700)
Added a new gc_urgent mode, GC_URGENT_LOW, in which mode
F2FS will lower the bar of checking idle in order to
process outstanding discard commands and GC a little bit
aggressively.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Documentation/ABI/testing/sysfs-fs-f2fs
fs/f2fs/f2fs.h
fs/f2fs/gc.c
fs/f2fs/segment.c
fs/f2fs/sysfs.c

index 4bb93a06d8abc52bb3cc6e5bc38005c202294d10..7f730c4c8df225ed07335a529678cd05b9248f99 100644 (file)
@@ -229,7 +229,9 @@ Date:               August 2017
 Contact:       "Jaegeuk Kim" <jaegeuk@kernel.org>
 Description:   Do background GC agressively when set. When gc_urgent = 1,
                background thread starts to do GC by given gc_urgent_sleep_time
-               interval. It is set to 0 by default.
+               interval. When gc_urgent = 2, F2FS will lower the bar of
+               checking idle in order to process outstanding discard commands
+               and GC a little bit aggressively. It is set to 0 by default.
 
 What:          /sys/fs/f2fs/<disk>/gc_urgent_sleep_time
 Date:          August 2017
index c98a9182862b23e01866443662bcdbfce283f8ee..b747223860d57b753ff02e71fb9151a60a88e168 100644 (file)
@@ -1268,7 +1268,8 @@ enum {
        GC_NORMAL,
        GC_IDLE_CB,
        GC_IDLE_GREEDY,
-       GC_URGENT,
+       GC_URGENT_HIGH,
+       GC_URGENT_LOW,
 };
 
 enum {
@@ -1525,6 +1526,7 @@ struct f2fs_sb_info {
        unsigned int cur_victim_sec;            /* current victim section num */
        unsigned int gc_mode;                   /* current GC state */
        unsigned int next_victim_seg[2];        /* next segment in victim section */
+
        /* for skip statistic */
        unsigned int atomic_files;              /* # of opened atomic file */
        unsigned long long skipped_atomic_files[2];     /* FG_GC and BG_GC */
@@ -2465,7 +2467,7 @@ static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep,
 
 static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
 {
-       if (sbi->gc_mode == GC_URGENT)
+       if (sbi->gc_mode == GC_URGENT_HIGH)
                return true;
 
        if (get_pages(sbi, F2FS_RD_DATA) || get_pages(sbi, F2FS_RD_NODE) ||
@@ -2483,6 +2485,10 @@ static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
                        atomic_read(&SM_I(sbi)->fcc_info->queued_flush))
                return false;
 
+       if (sbi->gc_mode == GC_URGENT_LOW &&
+                       (type == DISCARD_TIME || type == GC_TIME))
+               return true;
+
        return f2fs_time_over(sbi, type);
 }
 
index 9a40761445d3cc0bd3166e236922e9ab929266aa..11b4adde9baf0252361b47dbcaf06a0520ad1d70 100644 (file)
@@ -82,7 +82,7 @@ static int gc_thread_func(void *data)
                 * invalidated soon after by user update or deletion.
                 * So, I'd like to wait some time to collect dirty segments.
                 */
-               if (sbi->gc_mode == GC_URGENT) {
+               if (sbi->gc_mode == GC_URGENT_HIGH) {
                        wait_ms = gc_th->urgent_sleep_time;
                        down_write(&sbi->gc_lock);
                        goto do_gc;
@@ -176,7 +176,7 @@ static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type)
                gc_mode = GC_CB;
                break;
        case GC_IDLE_GREEDY:
-       case GC_URGENT:
+       case GC_URGENT_HIGH:
                gc_mode = GC_GREEDY;
                break;
        }
@@ -211,7 +211,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
         * foreground GC and urgent GC cases.
         */
        if (gc_type != FG_GC &&
-                       (sbi->gc_mode != GC_URGENT) &&
+                       (sbi->gc_mode != GC_URGENT_HIGH) &&
                        p->max_search > sbi->max_victim_search)
                p->max_search = sbi->max_victim_search;
 
index c35614d255e143c73720998c6e359ed7e991a31a..40dd29cfc83da712d75c840a3ed718a0c25a8837 100644 (file)
@@ -174,7 +174,7 @@ bool f2fs_need_SSR(struct f2fs_sb_info *sbi)
 
        if (f2fs_lfs_mode(sbi))
                return false;
-       if (sbi->gc_mode == GC_URGENT)
+       if (sbi->gc_mode == GC_URGENT_HIGH)
                return true;
        if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
                return true;
@@ -1759,7 +1759,7 @@ static int issue_discard_thread(void *data)
                        continue;
                }
 
-               if (sbi->gc_mode == GC_URGENT)
+               if (sbi->gc_mode == GC_URGENT_HIGH)
                        __init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1);
 
                sb_start_intwrite(sbi->sb);
index e877c59b9fdb4eed2ba28a9dbf2114452304da69..2a140657fc4db49c2e2a6dfe66f897b72ed9e5d2 100644 (file)
@@ -350,16 +350,20 @@ out:
                return -EINVAL;
 
        if (!strcmp(a->attr.name, "gc_urgent")) {
-               if (t >= 1) {
-                       sbi->gc_mode = GC_URGENT;
+               if (t == 0) {
+                       sbi->gc_mode = GC_NORMAL;
+               } else if (t == 1) {
+                       sbi->gc_mode = GC_URGENT_HIGH;
                        if (sbi->gc_thread) {
                                sbi->gc_thread->gc_wake = 1;
                                wake_up_interruptible_all(
                                        &sbi->gc_thread->gc_wait_queue_head);
                                wake_up_discard_thread(sbi, true);
                        }
+               } else if (t == 2) {
+                       sbi->gc_mode = GC_URGENT_LOW;
                } else {
-                       sbi->gc_mode = GC_NORMAL;
+                       return -EINVAL;
                }
                return count;
        }