Messages in this thread Patch in this message | | | From | Yangtao Li <> | Subject | [PATCH] f2fs: add discard_cpuset mount opt | Date | Wed, 1 Mar 2023 23:22:12 +0800 |
| |
It makes the discard process run faster on a more powerful CPU, or not.
Signed-off-by: Yangtao Li <frank.li@vivo.com> --- Documentation/filesystems/f2fs.rst | 2 ++ fs/f2fs/f2fs.h | 1 + fs/f2fs/segment.c | 8 +++++- fs/f2fs/super.c | 39 ++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst index 2055e72871fe..dc005f3b784a 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -351,6 +351,8 @@ age_extent_cache Enable an age extent cache based on rb-tree. It records data block update frequency of the extent per inode, in order to provide better temperature hints for data block allocation. +discard_cpuset=%u Set the cpumask of dicard thread, it makes the discard + process run faster on a more powerful CPU, or not. ======================== ============================================================ Debugfs Entries diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b0ab2062038a..62ce02a87d33 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -183,6 +183,7 @@ struct f2fs_mount_info { int compress_mode; /* compression mode */ unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */ unsigned char noextensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */ + struct cpumask discard_cpumask; /* discard thread cpumask */ }; #define F2FS_FEATURE_ENCRYPT 0x0001 diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 227e25836173..2648c564833e 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2054,11 +2054,17 @@ int f2fs_start_discard_thread(struct f2fs_sb_info *sbi) if (!f2fs_realtime_discard_enable(sbi)) return 0; - dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi, + dcc->f2fs_issue_discard = kthread_create(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); dcc->f2fs_issue_discard = NULL; + } else { + if (!cpumask_empty(&F2FS_OPTION(sbi).discard_cpumask)) { + kthread_bind_mask(dcc->f2fs_issue_discard, + &F2FS_OPTION(sbi).discard_cpumask); + } + wake_up_process(dcc->f2fs_issue_discard); } return err; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index fbaaabbcd6de..e2d0fcc2369c 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -164,6 +164,7 @@ enum { Opt_discard_unit, Opt_memory_mode, Opt_age_extent_cache, + Opt_discard_cpuset, Opt_err, }; @@ -243,6 +244,7 @@ static match_table_t f2fs_tokens = { {Opt_discard_unit, "discard_unit=%s"}, {Opt_memory_mode, "memory=%s"}, {Opt_age_extent_cache, "age_extent_cache"}, + {Opt_discard_cpuset, "discard_cpuset=%u"}, {Opt_err, NULL}, }; @@ -1256,6 +1258,22 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) case Opt_age_extent_cache: set_opt(sbi, AGE_EXTENT_CACHE); break; + case Opt_discard_cpuset: + if (!f2fs_hw_support_discard(sbi)) { + f2fs_warn(sbi, "device does not support discard"); + break; + } + + if (args->from && match_int(args, &arg)) + return -EINVAL; + + if (!cpu_possible(arg)) { + f2fs_err(sbi, "invalid cpu%d for discard_cpuset", arg); + return -EINVAL; + } + + cpumask_set_cpu(arg, &F2FS_OPTION(sbi).discard_cpumask); + break; default: f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value", p); @@ -1358,6 +1376,14 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) f2fs_err(sbi, "Allow to mount readonly mode only"); return -EROFS; } + + if (!cpumask_empty(&F2FS_OPTION(sbi).discard_cpumask) && + !cpumask_intersects(cpu_online_mask, + &F2FS_OPTION(sbi).discard_cpumask)) { + f2fs_err(sbi, "Must include one online CPU for discard_cpuset"); + return -EINVAL; + } + return 0; } @@ -1884,6 +1910,7 @@ static inline void f2fs_show_compress_options(struct seq_file *seq, static int f2fs_show_options(struct seq_file *seq, struct dentry *root) { struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb); + unsigned int cpu; if (F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC) seq_printf(seq, ",background_gc=%s", "sync"); @@ -1909,6 +1936,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) seq_printf(seq, ",discard_unit=%s", "segment"); else if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SECTION) seq_printf(seq, ",discard_unit=%s", "section"); + for_each_cpu(cpu, &F2FS_OPTION(sbi).discard_cpumask) + seq_printf(seq, ",discard_cpuset=%u", cpu); } else { seq_puts(seq, ",nodiscard"); } @@ -2222,6 +2251,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) 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 cpumask old_discard_cpumask; #ifdef CONFIG_QUOTA int i, j; #endif @@ -2232,6 +2262,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) */ org_mount_opt = sbi->mount_opt; old_sb_flags = sb->s_flags; + cpumask_copy(&old_discard_cpumask, &F2FS_OPTION(sbi).discard_cpumask); #ifdef CONFIG_QUOTA org_mount_opt.s_jquota_fmt = F2FS_OPTION(sbi).s_jquota_fmt; @@ -2340,6 +2371,13 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; } + if (!cpumask_equal(&F2FS_OPTION(sbi).discard_cpumask, + &old_discard_cpumask)) { + err = -EINVAL; + f2fs_warn(sbi, "switch discard_cpuset option is not allowed"); + goto restore_opts; + } + if ((*flags & SB_RDONLY) && test_opt(sbi, DISABLE_CHECKPOINT)) { err = -EINVAL; f2fs_warn(sbi, "disabling checkpoint not compatible with read-only"); @@ -2481,6 +2519,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i]; } #endif + cpumask_copy(&F2FS_OPTION(sbi).discard_cpumask, &old_discard_cpumask); sbi->mount_opt = org_mount_opt; sb->s_flags = old_sb_flags; return err; -- 2.25.1
| |