f2fs: Don't create discard thread when device doesn't support realtime discard
authorFengnan Chang <changfengnan@vivo.com>
Thu, 19 Aug 2021 08:02:37 +0000 (16:02 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Mon, 30 Aug 2021 17:12:46 +0000 (10:12 -0700)
Don't create discard thread when device doesn't support realtime discard
or user specifies nodiscard mount option.

Signed-off-by: Fengnan Chang <changfengnan@vivo.com>
Signed-off-by: Yangtao Li <frank.li@vivo.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/segment.c
fs/f2fs/super.c

index 30134307a404c358a1031a39401e2a877f2eac16..c24f03e054cb8f742da2116bcf33a334ce9abbc5 100644 (file)
@@ -3448,6 +3448,7 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi);
 void f2fs_destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free);
 void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr);
 bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr);
+int f2fs_start_discard_thread(struct f2fs_sb_info *sbi);
 void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi);
 void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi);
 bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi);
index 73abec9988e983407c2a21ebc46da5cb178b9c47..a135d22474154c35c108a587db9fb2be12bac0d4 100644 (file)
@@ -2115,9 +2115,25 @@ wakeup:
        wake_up_discard_thread(sbi, false);
 }
 
-static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
+int f2fs_start_discard_thread(struct f2fs_sb_info *sbi)
 {
        dev_t dev = sbi->sb->s_bdev->bd_dev;
+       struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+       int err = 0;
+
+       if (!f2fs_realtime_discard_enable(sbi))
+               return 0;
+
+       dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi,
+                               "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev));
+       if (IS_ERR(dcc->f2fs_issue_discard))
+               err = PTR_ERR(dcc->f2fs_issue_discard);
+
+       return err;
+}
+
+static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
+{
        struct discard_cmd_control *dcc;
        int err = 0, i;
 
@@ -2155,13 +2171,10 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
        init_waitqueue_head(&dcc->discard_wait_queue);
        SM_I(sbi)->dcc_info = dcc;
 init_thread:
-       dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi,
-                               "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev));
-       if (IS_ERR(dcc->f2fs_issue_discard)) {
-               err = PTR_ERR(dcc->f2fs_issue_discard);
+       err = f2fs_start_discard_thread(sbi);
+       if (err) {
                kfree(dcc);
                SM_I(sbi)->dcc_info = NULL;
-               return err;
        }
 
        return err;
index f5148f2fd8848c5feea93321d36d585ec8c4053b..d18271f3d1903685b49b34d4c6d210dc62eab749 100644 (file)
@@ -2105,12 +2105,15 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
        bool need_restart_gc = false, need_stop_gc = false;
        bool need_restart_ckpt = false, need_stop_ckpt = false;
        bool need_restart_flush = false, need_stop_flush = false;
+       bool need_restart_discard = false, need_stop_discard = false;
        bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE);
        bool enable_checkpoint = !test_opt(sbi, DISABLE_CHECKPOINT);
        bool no_io_align = !F2FS_IO_ALIGNED(sbi);
        bool no_atgc = !test_opt(sbi, ATGC);
+       bool no_discard = !test_opt(sbi, DISCARD);
        bool no_compress_cache = !test_opt(sbi, COMPRESS_CACHE);
        bool block_unit_discard = f2fs_block_unit_discard(sbi);
+       struct discard_cmd_control *dcc;
 #ifdef CONFIG_QUOTA
        int i, j;
 #endif
@@ -2282,11 +2285,26 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
                need_stop_flush = true;
        }
 
+       if (no_discard == !!test_opt(sbi, DISCARD)) {
+               if (test_opt(sbi, DISCARD)) {
+                       err = f2fs_start_discard_thread(sbi);
+                       if (err)
+                               goto restore_flush;
+                       need_stop_discard = true;
+               } else {
+                       dcc = SM_I(sbi)->dcc_info;
+                       f2fs_stop_discard_thread(sbi);
+                       if (atomic_read(&dcc->discard_cmd_cnt))
+                               f2fs_issue_discard_timeout(sbi);
+                       need_restart_discard = true;
+               }
+       }
+
        if (enable_checkpoint == !!test_opt(sbi, DISABLE_CHECKPOINT)) {
                if (test_opt(sbi, DISABLE_CHECKPOINT)) {
                        err = f2fs_disable_checkpoint(sbi);
                        if (err)
-                               goto restore_flush;
+                               goto restore_discard;
                } else {
                        f2fs_enable_checkpoint(sbi);
                }
@@ -2306,6 +2324,13 @@ skip:
        adjust_unusable_cap_perc(sbi);
        *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
        return 0;
+restore_discard:
+       if (need_restart_discard) {
+               if (f2fs_start_discard_thread(sbi))
+                       f2fs_warn(sbi, "discard has been stopped");
+       } else if (need_stop_discard) {
+               f2fs_stop_discard_thread(sbi);
+       }
 restore_flush:
        if (need_restart_flush) {
                if (f2fs_create_flush_cmd_control(sbi))