From: Hongbo Li <lihongbo22@huawei.com>
To: Chao Yu <chao@kernel.org>, <jaegeuk@kernel.org>
Cc: <linux-f2fs-devel@lists.sourceforge.net>, <sandeen@redhat.com>,
<linux-fsdevel@vger.kernel.org>
Subject: Re: [PATCH v4 2/7] f2fs: move the option parser into handle_mount_opt
Date: Mon, 7 Jul 2025 21:20:59 +0800 [thread overview]
Message-ID: <2601f452-5139-4a1b-8a5c-d305b27364c0@huawei.com> (raw)
In-Reply-To: <12957e9a-df4b-4649-a298-532f874bbc6f@kernel.org>
On 2025/7/4 11:27, Chao Yu wrote:
> On 6/2/25 17:02, Hongbo Li wrote:
>> In handle_mount_opt, we use fs_parameter to parse each option.
>> However we're still using the old API to get the options string.
>> Using fsparams parse_options allows us to remove many of the Opt_
>> enums, so remove them.
>>
>> The checkpoint disable cap (or percent) involves rather complex
>> parsing; we retain the old match_table mechanism for this, which
>> handles it well.
>>
>> There are some changes about parsing options:
>> 1. For `active_logs`, `inline_xattr_size` and `fault_injection`,
>> we use s32 type according the internal structure to record the
>> option's value.
>>
>> Signed-off-by: Hongbo Li <lihongbo22@huawei.com>
>> [sandeen: forward port, minor fixes and updates]
>> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
>> [hongbo: minor cleanup]
>> Signed-off-by: Hongbo Li <lihongbo22@huawei.com>
>> ---
>> fs/f2fs/super.c | 1068 ++++++++++++++++++-----------------------------
>> 1 file changed, 413 insertions(+), 655 deletions(-)
>>
>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>> index 996633b8379e..dff2419ba905 100644
>> --- a/fs/f2fs/super.c
>> +++ b/fs/f2fs/super.c
>> @@ -27,6 +27,7 @@
>> #include <linux/part_stat.h>
>> #include <linux/zstd.h>
>> #include <linux/lz4.h>
>> +#include <linux/ctype.h>
>> #include <linux/fs_parser.h>
>>
>> #include "f2fs.h"
>> @@ -126,29 +127,20 @@ enum {
>> Opt_disable_roll_forward,
>> Opt_norecovery,
>> Opt_discard,
>> - Opt_nodiscard,
>> Opt_noheap,
>> Opt_heap,
>> Opt_user_xattr,
>> - Opt_nouser_xattr,
>> Opt_acl,
>> - Opt_noacl,
>> Opt_active_logs,
>> Opt_disable_ext_identify,
>> Opt_inline_xattr,
>> - Opt_noinline_xattr,
>> Opt_inline_xattr_size,
>> Opt_inline_data,
>> Opt_inline_dentry,
>> - Opt_noinline_dentry,
>> Opt_flush_merge,
>> - Opt_noflush_merge,
>> Opt_barrier,
>> - Opt_nobarrier,
>> Opt_fastboot,
>> Opt_extent_cache,
>> - Opt_noextent_cache,
>> - Opt_noinline_data,
>> Opt_data_flush,
>> Opt_reserve_root,
>> Opt_resgid,
>> @@ -157,21 +149,13 @@ enum {
>> Opt_fault_injection,
>> Opt_fault_type,
>> Opt_lazytime,
>> - Opt_nolazytime,
>> Opt_quota,
>> - Opt_noquota,
>> Opt_usrquota,
>> Opt_grpquota,
>> Opt_prjquota,
>> Opt_usrjquota,
>> Opt_grpjquota,
>> Opt_prjjquota,
>> - Opt_offusrjquota,
>> - Opt_offgrpjquota,
>> - Opt_offprjjquota,
>> - Opt_jqfmt_vfsold,
>> - Opt_jqfmt_vfsv0,
>> - Opt_jqfmt_vfsv1,
>> Opt_alloc,
>> Opt_fsync,
>> Opt_test_dummy_encryption,
>> @@ -181,17 +165,15 @@ enum {
>> Opt_checkpoint_disable_cap_perc,
>> Opt_checkpoint_enable,
>> Opt_checkpoint_merge,
>> - Opt_nocheckpoint_merge,
>> Opt_compress_algorithm,
>> Opt_compress_log_size,
>> - Opt_compress_extension,
>> Opt_nocompress_extension,
>> + Opt_compress_extension,
>> Opt_compress_chksum,
>> Opt_compress_mode,
>> Opt_compress_cache,
>> Opt_atgc,
>> Opt_gc_merge,
>> - Opt_nogc_merge,
>> Opt_discard_unit,
>> Opt_memory_mode,
>> Opt_age_extent_cache,
>> @@ -321,83 +303,12 @@ static const struct fs_parameter_spec f2fs_param_specs[] = {
>> {}
>> };
>>
>> -static match_table_t f2fs_tokens = {
>> - {Opt_gc_background, "background_gc=%s"},
>> - {Opt_disable_roll_forward, "disable_roll_forward"},
>> - {Opt_norecovery, "norecovery"},
>> - {Opt_discard, "discard"},
>> - {Opt_nodiscard, "nodiscard"},
>> - {Opt_noheap, "no_heap"},
>> - {Opt_heap, "heap"},
>> - {Opt_user_xattr, "user_xattr"},
>> - {Opt_nouser_xattr, "nouser_xattr"},
>> - {Opt_acl, "acl"},
>> - {Opt_noacl, "noacl"},
>> - {Opt_active_logs, "active_logs=%u"},
>> - {Opt_disable_ext_identify, "disable_ext_identify"},
>> - {Opt_inline_xattr, "inline_xattr"},
>> - {Opt_noinline_xattr, "noinline_xattr"},
>> - {Opt_inline_xattr_size, "inline_xattr_size=%u"},
>> - {Opt_inline_data, "inline_data"},
>> - {Opt_inline_dentry, "inline_dentry"},
>> - {Opt_noinline_dentry, "noinline_dentry"},
>> - {Opt_flush_merge, "flush_merge"},
>> - {Opt_noflush_merge, "noflush_merge"},
>> - {Opt_barrier, "barrier"},
>> - {Opt_nobarrier, "nobarrier"},
>> - {Opt_fastboot, "fastboot"},
>> - {Opt_extent_cache, "extent_cache"},
>> - {Opt_noextent_cache, "noextent_cache"},
>> - {Opt_noinline_data, "noinline_data"},
>> - {Opt_data_flush, "data_flush"},
>> - {Opt_reserve_root, "reserve_root=%u"},
>> - {Opt_resgid, "resgid=%u"},
>> - {Opt_resuid, "resuid=%u"},
>> - {Opt_mode, "mode=%s"},
>> - {Opt_fault_injection, "fault_injection=%u"},
>> - {Opt_fault_type, "fault_type=%u"},
>> - {Opt_lazytime, "lazytime"},
>> - {Opt_nolazytime, "nolazytime"},
>> - {Opt_quota, "quota"},
>> - {Opt_noquota, "noquota"},
>> - {Opt_usrquota, "usrquota"},
>> - {Opt_grpquota, "grpquota"},
>> - {Opt_prjquota, "prjquota"},
>> - {Opt_usrjquota, "usrjquota=%s"},
>> - {Opt_grpjquota, "grpjquota=%s"},
>> - {Opt_prjjquota, "prjjquota=%s"},
>> - {Opt_offusrjquota, "usrjquota="},
>> - {Opt_offgrpjquota, "grpjquota="},
>> - {Opt_offprjjquota, "prjjquota="},
>> - {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
>> - {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
>> - {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
>> - {Opt_alloc, "alloc_mode=%s"},
>> - {Opt_fsync, "fsync_mode=%s"},
>> - {Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
>> - {Opt_test_dummy_encryption, "test_dummy_encryption"},
>> - {Opt_inlinecrypt, "inlinecrypt"},
>> - {Opt_checkpoint_disable, "checkpoint=disable"},
>> - {Opt_checkpoint_disable_cap, "checkpoint=disable:%u"},
>> - {Opt_checkpoint_disable_cap_perc, "checkpoint=disable:%u%%"},
>> - {Opt_checkpoint_enable, "checkpoint=enable"},
>> - {Opt_checkpoint_merge, "checkpoint_merge"},
>> - {Opt_nocheckpoint_merge, "nocheckpoint_merge"},
>> - {Opt_compress_algorithm, "compress_algorithm=%s"},
>> - {Opt_compress_log_size, "compress_log_size=%u"},
>> - {Opt_compress_extension, "compress_extension=%s"},
>> - {Opt_nocompress_extension, "nocompress_extension=%s"},
>> - {Opt_compress_chksum, "compress_chksum"},
>> - {Opt_compress_mode, "compress_mode=%s"},
>> - {Opt_compress_cache, "compress_cache"},
>> - {Opt_atgc, "atgc"},
>> - {Opt_gc_merge, "gc_merge"},
>> - {Opt_nogc_merge, "nogc_merge"},
>> - {Opt_discard_unit, "discard_unit=%s"},
>> - {Opt_memory_mode, "memory=%s"},
>> - {Opt_age_extent_cache, "age_extent_cache"},
>> - {Opt_errors, "errors=%s"},
>> - {Opt_nat_bits, "nat_bits"},
>> +/* Resort to a match_table for this interestingly formatted option */
>> +static match_table_t f2fs_checkpoint_tokens = {
>> + {Opt_checkpoint_disable, "disable"},
>> + {Opt_checkpoint_disable_cap, "disable:%u"},
>> + {Opt_checkpoint_disable_cap_perc, "disable:%u%%"},
>> + {Opt_checkpoint_enable, "enable"},
>> {Opt_err, NULL},
>> };
>>
>> @@ -513,7 +424,7 @@ static void init_once(void *foo)
>> static const char * const quotatypes[] = INITQFNAMES;
>> #define QTYPE2NAME(t) (quotatypes[t])
>> static int f2fs_set_qf_name(struct f2fs_sb_info *sbi, int qtype,
>> - substring_t *args)
>> + struct fs_parameter *param)
>> {
>> struct super_block *sb = sbi->sb;
>> char *qname;
>> @@ -528,7 +439,7 @@ static int f2fs_set_qf_name(struct f2fs_sb_info *sbi, int qtype,
>> return 0;
>> }
>>
>> - qname = match_strdup(args);
>> + qname = kmemdup_nul(param->string, param->size, GFP_KERNEL);
>> if (!qname) {
>> f2fs_err(sbi, "Not enough memory for storing quotafile name");
>> return -ENOMEM;
>> @@ -613,14 +524,9 @@ static int f2fs_check_quota_options(struct f2fs_sb_info *sbi)
>> #endif
>>
>> static int f2fs_set_test_dummy_encryption(struct f2fs_sb_info *sbi,
>> - const char *opt,
>> - const substring_t *arg,
>> + const struct fs_parameter *param,
>> bool is_remount)
>> {
>> - struct fs_parameter param = {
>> - .type = fs_value_is_string,
>> - .string = arg->from ? arg->from : "",
>> - };
>> struct fscrypt_dummy_policy *policy =
>> &F2FS_OPTION(sbi).dummy_enc_policy;
>> int err;
>> @@ -646,17 +552,17 @@ static int f2fs_set_test_dummy_encryption(struct f2fs_sb_info *sbi,
>> return -EINVAL;
>> }
>>
>> - err = fscrypt_parse_test_dummy_encryption(¶m, policy);
>> + err = fscrypt_parse_test_dummy_encryption(param, policy);
>> if (err) {
>> if (err == -EEXIST)
>> f2fs_warn(sbi,
>> "Can't change test_dummy_encryption on remount");
>> else if (err == -EINVAL)
>> f2fs_warn(sbi, "Value of option \"%s\" is unrecognized",
>> - opt);
>> + param->key);
>> else
>> f2fs_warn(sbi, "Error processing option \"%s\" [%d]",
>> - opt, err);
>> + param->key, err);
>> return -EINVAL;
>> }
>> f2fs_warn(sbi, "Test dummy encryption mode enabled");
>> @@ -799,372 +705,269 @@ static int f2fs_set_zstd_level(struct f2fs_sb_info *sbi, const char *str)
>> #endif
>> #endif
>>
>> -static int parse_options(struct f2fs_sb_info *sbi, char *options, bool is_remount)
>> +static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
>> {
>> - substring_t args[MAX_OPT_ARGS];
>> + struct f2fs_sb_info *sbi = fc->s_fs_info;
>> #ifdef CONFIG_F2FS_FS_COMPRESSION
>> unsigned char (*ext)[F2FS_EXTENSION_LEN];
>> unsigned char (*noext)[F2FS_EXTENSION_LEN];
>> int ext_cnt, noext_cnt;
>> + char *name;
>> #endif
>> - char *p, *name;
>> - int arg = 0;
>> - kuid_t uid;
>> - kgid_t gid;
>> - int ret;
>> + substring_t args[MAX_OPT_ARGS];
>> + struct fs_parse_result result;
>> + bool is_remount;
>> + int token, ret, arg;
>>
>> - if (!options)
>> - return 0;
>> + token = fs_parse(fc, f2fs_param_specs, param, &result);
>> + if (token < 0)
>> + return token;
>>
>> - while ((p = strsep(&options, ",")) != NULL) {
>> - int token;
>> + is_remount = fc->purpose == FS_CONTEXT_FOR_RECONFIGURE;
>>
>> - if (!*p)
>> - continue;
>> - /*
>> - * Initialize args struct so we know whether arg was
>> - * found; some options take optional arguments.
>> - */
>> - args[0].to = args[0].from = NULL;
>> - token = match_token(p, f2fs_tokens, args);
>> -
>> - switch (token) {
>> - case Opt_gc_background:
>> - name = match_strdup(&args[0]);
>> -
>> - if (!name)
>> - return -ENOMEM;
>> - 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;
>> - }
>
> Missed to check this condition in f2fs_check_opt_consistency()?
>
Thanks for pointing this. Yeah, we should add this in
f2fs_check_opt_consistency like this:
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 0a070dadbb42..86938dd5491e 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1458,6 +1458,10 @@ static int f2fs_check_opt_consistency(struct
fs_context *fc,
* devices, but mandatory for host-managed zoned block devices.
*/
if (f2fs_sb_has_blkzoned(sbi)) {
+ if (F2FS_CTX_OPTION(ctx).bggc_mode == BGGC_MODE_OFF) {
+ f2fs_warn(sbi, "zoned devices need bggc");
+ return -EINVAL;
+ }
#ifdef CONFIG_BLK_DEV_ZONED
if ((ctx->spec_mask & F2FS_SPEC_discard_unit) &&
F2FS_CTX_INFO(ctx).discard_unit != DISCARD_UNIT_SECTION) {
Thanks,
Hongbo
> Thanks,
>
>> - F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_OFF;
>> - } else if (!strcmp(name, "sync")) {
>> - F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC;
>> - } else {
>> - kfree(name);
>> + switch (token) {
>> + case Opt_gc_background:
>> + F2FS_OPTION(sbi).bggc_mode = result.uint_32;
>> + break;
>> + case Opt_disable_roll_forward:
>> + set_opt(sbi, DISABLE_ROLL_FORWARD);
>> + break;
>> + case Opt_norecovery:
>> + /* requires ro mount, checked in f2fs_validate_options */
>> + set_opt(sbi, NORECOVERY);
>> + break;
>> + case Opt_discard:
>> + if (result.negated) {
>> + if (f2fs_hw_should_discard(sbi)) {
>> + f2fs_warn(sbi, "discard is required for zoned block devices");
>> return -EINVAL;
>> }
>> - kfree(name);
>> - break;
>> - case Opt_disable_roll_forward:
>> - set_opt(sbi, DISABLE_ROLL_FORWARD);
>> - break;
>> - case Opt_norecovery:
>> - /* requires ro mount, checked in f2fs_default_check */
>> - set_opt(sbi, NORECOVERY);
>> - break;
>> - case Opt_discard:
>> + clear_opt(sbi, DISCARD);
>> + } else {
>> if (!f2fs_hw_support_discard(sbi)) {
>> f2fs_warn(sbi, "device does not support discard");
>> break;
>> }
>> set_opt(sbi, DISCARD);
>> - break;
>> - case Opt_nodiscard:
>> - if (f2fs_hw_should_discard(sbi)) {
>> - f2fs_warn(sbi, "discard is required for zoned block devices");
>> - return -EINVAL;
>> - }
>> - clear_opt(sbi, DISCARD);
>> - break;
>> - case Opt_noheap:
>> - case Opt_heap:
>> - f2fs_warn(sbi, "heap/no_heap options were deprecated");
>> - break;
>> + }
>> + break;
>> + case Opt_noheap:
>> + case Opt_heap:
>> + f2fs_warn(sbi, "heap/no_heap options were deprecated");
>> + break;
>> #ifdef CONFIG_F2FS_FS_XATTR
>> - case Opt_user_xattr:
>> - set_opt(sbi, XATTR_USER);
>> - break;
>> - case Opt_nouser_xattr:
>> + case Opt_user_xattr:
>> + if (result.negated)
>> clear_opt(sbi, XATTR_USER);
>> - break;
>> - case Opt_inline_xattr:
>> - set_opt(sbi, INLINE_XATTR);
>> - break;
>> - case Opt_noinline_xattr:
>> + else
>> + set_opt(sbi, XATTR_USER);
>> + break;
>> + case Opt_inline_xattr:
>> + if (result.negated)
>> clear_opt(sbi, INLINE_XATTR);
>> - break;
>> - case Opt_inline_xattr_size:
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - set_opt(sbi, INLINE_XATTR_SIZE);
>> - F2FS_OPTION(sbi).inline_xattr_size = arg;
>> - break;
>> + else
>> + set_opt(sbi, INLINE_XATTR);
>> + break;
>> + case Opt_inline_xattr_size:
>> + set_opt(sbi, INLINE_XATTR_SIZE);
>> + F2FS_OPTION(sbi).inline_xattr_size = result.int_32;
>> + break;
>> #else
>> - case Opt_user_xattr:
>> - case Opt_nouser_xattr:
>> - case Opt_inline_xattr:
>> - case Opt_noinline_xattr:
>> - case Opt_inline_xattr_size:
>> - f2fs_info(sbi, "xattr options not supported");
>> - break;
>> + case Opt_user_xattr:
>> + case Opt_inline_xattr:
>> + case Opt_inline_xattr_size:
>> + f2fs_info(sbi, "%s options not supported", param->key);
>> + break;
>> #endif
>> #ifdef CONFIG_F2FS_FS_POSIX_ACL
>> - case Opt_acl:
>> - set_opt(sbi, POSIX_ACL);
>> - break;
>> - case Opt_noacl:
>> + case Opt_acl:
>> + if (result.negated)
>> clear_opt(sbi, POSIX_ACL);
>> - break;
>> + else
>> + set_opt(sbi, POSIX_ACL);
>> + break;
>> #else
>> - case Opt_acl:
>> - case Opt_noacl:
>> - f2fs_info(sbi, "acl options not supported");
>> - break;
>> + case Opt_acl:
>> + f2fs_info(sbi, "%s options not supported", param->key);
>> + break;
>> #endif
>> - case Opt_active_logs:
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - if (arg != 2 && arg != 4 &&
>> - arg != NR_CURSEG_PERSIST_TYPE)
>> - return -EINVAL;
>> - F2FS_OPTION(sbi).active_logs = arg;
>> - break;
>> - case Opt_disable_ext_identify:
>> - set_opt(sbi, DISABLE_EXT_IDENTIFY);
>> - break;
>> - case Opt_inline_data:
>> + case Opt_active_logs:
>> + if (result.int_32 != 2 && result.int_32 != 4 &&
>> + result.int_32 != NR_CURSEG_PERSIST_TYPE)
>> + return -EINVAL;
>> + F2FS_OPTION(sbi).active_logs = result.int_32;
>> + break;
>> + case Opt_disable_ext_identify:
>> + set_opt(sbi, DISABLE_EXT_IDENTIFY);
>> + break;
>> + case Opt_inline_data:
>> + if (result.negated)
>> + clear_opt(sbi, INLINE_DATA);
>> + else
>> set_opt(sbi, INLINE_DATA);
>> - break;
>> - case Opt_inline_dentry:
>> - set_opt(sbi, INLINE_DENTRY);
>> - break;
>> - case Opt_noinline_dentry:
>> + break;
>> + case Opt_inline_dentry:
>> + if (result.negated)
>> clear_opt(sbi, INLINE_DENTRY);
>> - break;
>> - case Opt_flush_merge:
>> - set_opt(sbi, FLUSH_MERGE);
>> - break;
>> - case Opt_noflush_merge:
>> + else
>> + set_opt(sbi, INLINE_DENTRY);
>> + break;
>> + case Opt_flush_merge:
>> + if (result.negated)
>> clear_opt(sbi, FLUSH_MERGE);
>> - break;
>> - case Opt_nobarrier:
>> + else
>> + set_opt(sbi, FLUSH_MERGE);
>> + break;
>> + case Opt_barrier:
>> + if (result.negated)
>> set_opt(sbi, NOBARRIER);
>> - break;
>> - case Opt_barrier:
>> + else
>> clear_opt(sbi, NOBARRIER);
>> - break;
>> - case Opt_fastboot:
>> - set_opt(sbi, FASTBOOT);
>> - break;
>> - case Opt_extent_cache:
>> - set_opt(sbi, READ_EXTENT_CACHE);
>> - break;
>> - case Opt_noextent_cache:
>> + break;
>> + case Opt_fastboot:
>> + set_opt(sbi, FASTBOOT);
>> + break;
>> + case Opt_extent_cache:
>> + if (result.negated) {
>> if (f2fs_sb_has_device_alias(sbi)) {
>> f2fs_err(sbi, "device aliasing requires extent cache");
>> return -EINVAL;
>> }
>> clear_opt(sbi, READ_EXTENT_CACHE);
>> - break;
>> - case Opt_noinline_data:
>> - clear_opt(sbi, INLINE_DATA);
>> - break;
>> - case Opt_data_flush:
>> - set_opt(sbi, DATA_FLUSH);
>> - break;
>> - case Opt_reserve_root:
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - if (test_opt(sbi, RESERVE_ROOT)) {
>> - f2fs_info(sbi, "Preserve previous reserve_root=%u",
>> - F2FS_OPTION(sbi).root_reserved_blocks);
>> - } else {
>> - F2FS_OPTION(sbi).root_reserved_blocks = arg;
>> - set_opt(sbi, RESERVE_ROOT);
>> - }
>> - break;
>> - case Opt_resuid:
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - uid = make_kuid(current_user_ns(), arg);
>> - if (!uid_valid(uid)) {
>> - f2fs_err(sbi, "Invalid uid value %d", arg);
>> - return -EINVAL;
>> - }
>> - F2FS_OPTION(sbi).s_resuid = uid;
>> - break;
>> - case Opt_resgid:
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - gid = make_kgid(current_user_ns(), arg);
>> - if (!gid_valid(gid)) {
>> - f2fs_err(sbi, "Invalid gid value %d", arg);
>> - return -EINVAL;
>> - }
>> - F2FS_OPTION(sbi).s_resgid = gid;
>> - break;
>> - case Opt_mode:
>> - name = match_strdup(&args[0]);
>> -
>> - if (!name)
>> - return -ENOMEM;
>> - if (!strcmp(name, "adaptive")) {
>> - F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE;
>> - } else if (!strcmp(name, "lfs")) {
>> - F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS;
>> - } else if (!strcmp(name, "fragment:segment")) {
>> - F2FS_OPTION(sbi).fs_mode = FS_MODE_FRAGMENT_SEG;
>> - } else if (!strcmp(name, "fragment:block")) {
>> - F2FS_OPTION(sbi).fs_mode = FS_MODE_FRAGMENT_BLK;
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - kfree(name);
>> - break;
>> + } else
>> + set_opt(sbi, READ_EXTENT_CACHE);
>> + break;
>> + case Opt_data_flush:
>> + set_opt(sbi, DATA_FLUSH);
>> + break;
>> + case Opt_reserve_root:
>> + if (test_opt(sbi, RESERVE_ROOT)) {
>> + f2fs_info(sbi, "Preserve previous reserve_root=%u",
>> + F2FS_OPTION(sbi).root_reserved_blocks);
>> + } else {
>> + F2FS_OPTION(sbi).root_reserved_blocks = result.int_32;
>> + set_opt(sbi, RESERVE_ROOT);
>> + }
>> + break;
>> + case Opt_resuid:
>> + F2FS_OPTION(sbi).s_resuid = result.uid;
>> + break;
>> + case Opt_resgid:
>> + F2FS_OPTION(sbi).s_resgid = result.gid;
>> + break;
>> + case Opt_mode:
>> + F2FS_OPTION(sbi).fs_mode = result.uint_32;
>> + break;
>> #ifdef CONFIG_F2FS_FAULT_INJECTION
>> - case Opt_fault_injection:
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - if (f2fs_build_fault_attr(sbi, arg, 0, FAULT_RATE))
>> - return -EINVAL;
>> - set_opt(sbi, FAULT_INJECTION);
>> - break;
>> + case Opt_fault_injection:
>> + if (f2fs_build_fault_attr(sbi, result.int_32, 0, FAULT_RATE))
>> + return -EINVAL;
>> + set_opt(sbi, FAULT_INJECTION);
>> + break;
>>
>> - case Opt_fault_type:
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - if (f2fs_build_fault_attr(sbi, 0, arg, FAULT_TYPE))
>> - return -EINVAL;
>> - set_opt(sbi, FAULT_INJECTION);
>> - break;
>> + case Opt_fault_type:
>> + if (f2fs_build_fault_attr(sbi, 0, result.int_32, FAULT_TYPE))
>> + return -EINVAL;
>> + set_opt(sbi, FAULT_INJECTION);
>> + break;
>> #else
>> - case Opt_fault_injection:
>> - case Opt_fault_type:
>> - f2fs_info(sbi, "fault injection options not supported");
>> - break;
>> + case Opt_fault_injection:
>> + case Opt_fault_type:
>> + f2fs_info(sbi, "%s options not supported", param->key);
>> + break;
>> #endif
>> - case Opt_lazytime:
>> - set_opt(sbi, LAZYTIME);
>> - break;
>> - case Opt_nolazytime:
>> + case Opt_lazytime:
>> + if (result.negated)
>> clear_opt(sbi, LAZYTIME);
>> - break;
>> + else
>> + set_opt(sbi, LAZYTIME);
>> + break;
>> #ifdef CONFIG_QUOTA
>> - case Opt_quota:
>> - case Opt_usrquota:
>> - set_opt(sbi, USRQUOTA);
>> - break;
>> - case Opt_grpquota:
>> - set_opt(sbi, GRPQUOTA);
>> - break;
>> - case Opt_prjquota:
>> - set_opt(sbi, PRJQUOTA);
>> - break;
>> - case Opt_usrjquota:
>> - ret = f2fs_set_qf_name(sbi, USRQUOTA, &args[0]);
>> - if (ret)
>> - return ret;
>> - break;
>> - case Opt_grpjquota:
>> - ret = f2fs_set_qf_name(sbi, GRPQUOTA, &args[0]);
>> - if (ret)
>> - return ret;
>> - break;
>> - case Opt_prjjquota:
>> - ret = f2fs_set_qf_name(sbi, PRJQUOTA, &args[0]);
>> - if (ret)
>> - return ret;
>> - break;
>> - case Opt_offusrjquota:
>> - ret = f2fs_clear_qf_name(sbi, USRQUOTA);
>> - if (ret)
>> - return ret;
>> - break;
>> - case Opt_offgrpjquota:
>> - ret = f2fs_clear_qf_name(sbi, GRPQUOTA);
>> - if (ret)
>> - return ret;
>> - break;
>> - case Opt_offprjjquota:
>> - ret = f2fs_clear_qf_name(sbi, PRJQUOTA);
>> - if (ret)
>> - return ret;
>> - break;
>> - case Opt_jqfmt_vfsold:
>> - F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_OLD;
>> - break;
>> - case Opt_jqfmt_vfsv0:
>> - F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_V0;
>> - break;
>> - case Opt_jqfmt_vfsv1:
>> - F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_V1;
>> - break;
>> - case Opt_noquota:
>> + case Opt_quota:
>> + if (result.negated) {
>> clear_opt(sbi, QUOTA);
>> clear_opt(sbi, USRQUOTA);
>> clear_opt(sbi, GRPQUOTA);
>> clear_opt(sbi, PRJQUOTA);
>> - break;
>> + } else
>> + set_opt(sbi, USRQUOTA);
>> + break;
>> + case Opt_usrquota:
>> + set_opt(sbi, USRQUOTA);
>> + break;
>> + case Opt_grpquota:
>> + set_opt(sbi, GRPQUOTA);
>> + break;
>> + case Opt_prjquota:
>> + set_opt(sbi, PRJQUOTA);
>> + break;
>> + case Opt_usrjquota:
>> + if (!*param->string)
>> + ret = f2fs_clear_qf_name(sbi, USRQUOTA);
>> + else
>> + ret = f2fs_set_qf_name(sbi, USRQUOTA, param);
>> + if (ret)
>> + return ret;
>> + break;
>> + case Opt_grpjquota:
>> + if (!*param->string)
>> + ret = f2fs_clear_qf_name(sbi, GRPQUOTA);
>> + else
>> + ret = f2fs_set_qf_name(sbi, GRPQUOTA, param);
>> + if (ret)
>> + return ret;
>> + break;
>> + case Opt_prjjquota:
>> + if (!*param->string)
>> + ret = f2fs_clear_qf_name(sbi, PRJQUOTA);
>> + else
>> + ret = f2fs_set_qf_name(sbi, PRJQUOTA, param);
>> + if (ret)
>> + return ret;
>> + break;
>> + case Opt_jqfmt:
>> + F2FS_OPTION(sbi).s_jquota_fmt = result.uint_32;
>> + break;
>> #else
>> - case Opt_quota:
>> - case Opt_usrquota:
>> - case Opt_grpquota:
>> - case Opt_prjquota:
>> - case Opt_usrjquota:
>> - case Opt_grpjquota:
>> - case Opt_prjjquota:
>> - case Opt_offusrjquota:
>> - case Opt_offgrpjquota:
>> - case Opt_offprjjquota:
>> - case Opt_jqfmt_vfsold:
>> - case Opt_jqfmt_vfsv0:
>> - case Opt_jqfmt_vfsv1:
>> - case Opt_noquota:
>> - f2fs_info(sbi, "quota operations not supported");
>> - break;
>> + case Opt_quota:
>> + case Opt_usrquota:
>> + case Opt_grpquota:
>> + case Opt_prjquota:
>> + case Opt_usrjquota:
>> + case Opt_grpjquota:
>> + case Opt_prjjquota:
>> + f2fs_info(sbi, "quota operations not supported");
>> + break;
>> #endif
>> - case Opt_alloc:
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> -
>> - if (!strcmp(name, "default")) {
>> - F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
>> - } else if (!strcmp(name, "reuse")) {
>> - F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE;
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - kfree(name);
>> - break;
>> - case Opt_fsync:
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> - if (!strcmp(name, "posix")) {
>> - F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX;
>> - } else if (!strcmp(name, "strict")) {
>> - F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_STRICT;
>> - } else if (!strcmp(name, "nobarrier")) {
>> - F2FS_OPTION(sbi).fsync_mode =
>> - FSYNC_MODE_NOBARRIER;
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - kfree(name);
>> - break;
>> - case Opt_test_dummy_encryption:
>> - ret = f2fs_set_test_dummy_encryption(sbi, p, &args[0],
>> - is_remount);
>> - if (ret)
>> - return ret;
>> - break;
>> - case Opt_inlinecrypt:
>> + case Opt_alloc:
>> + F2FS_OPTION(sbi).alloc_mode = result.uint_32;
>> + break;
>> + case Opt_fsync:
>> + F2FS_OPTION(sbi).fsync_mode = result.uint_32;
>> + break;
>> + case Opt_test_dummy_encryption:
>> + ret = f2fs_set_test_dummy_encryption(sbi, param, is_remount);
>> + if (ret)
>> + return ret;
>> + break;
>> + case Opt_inlinecrypt:
>> #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
>> - set_opt(sbi, INLINECRYPT);
>> + set_opt(sbi, INLINECRYPT);
>> #else
>> - f2fs_info(sbi, "inline encryption not supported");
>> + f2fs_info(sbi, "inline encryption not supported");
>> #endif
>> - break;
>> + break;
>> + case Opt_checkpoint:
>> + /*
>> + * Initialize args struct so we know whether arg was
>> + * found; some options take optional arguments.
>> + */
>> + args[0].from = args[0].to = NULL;
>> + arg = 0;
>> +
>> + /* revert to match_table for checkpoint= options */
>> + token = match_token(param->string, f2fs_checkpoint_tokens, args);
>> + switch (token) {
>> case Opt_checkpoint_disable_cap_perc:
>> if (args->from && match_int(args, &arg))
>> return -EINVAL;
>> @@ -1185,270 +988,225 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options, bool is_remoun
>> case Opt_checkpoint_enable:
>> clear_opt(sbi, DISABLE_CHECKPOINT);
>> break;
>> - case Opt_checkpoint_merge:
>> - set_opt(sbi, MERGE_CHECKPOINT);
>> - break;
>> - case Opt_nocheckpoint_merge:
>> + default:
>> + return -EINVAL;
>> + }
>> + break;
>> + case Opt_checkpoint_merge:
>> + if (result.negated)
>> clear_opt(sbi, MERGE_CHECKPOINT);
>> - break;
>> + else
>> + set_opt(sbi, MERGE_CHECKPOINT);
>> + break;
>> #ifdef CONFIG_F2FS_FS_COMPRESSION
>> - case Opt_compress_algorithm:
>> - if (!f2fs_sb_has_compression(sbi)) {
>> - f2fs_info(sbi, "Image doesn't support compression");
>> - break;
>> - }
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> - if (!strcmp(name, "lzo")) {
>> + case Opt_compress_algorithm:
>> + if (!f2fs_sb_has_compression(sbi)) {
>> + f2fs_info(sbi, "Image doesn't support compression");
>> + break;
>> + }
>> + name = param->string;
>> + if (!strcmp(name, "lzo")) {
>> #ifdef CONFIG_F2FS_FS_LZO
>> - F2FS_OPTION(sbi).compress_level = 0;
>> - F2FS_OPTION(sbi).compress_algorithm =
>> - COMPRESS_LZO;
>> + F2FS_OPTION(sbi).compress_level = 0;
>> + F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZO;
>> #else
>> - f2fs_info(sbi, "kernel doesn't support lzo compression");
>> + f2fs_info(sbi, "kernel doesn't support lzo compression");
>> #endif
>> - } else if (!strncmp(name, "lz4", 3)) {
>> + } else if (!strncmp(name, "lz4", 3)) {
>> #ifdef CONFIG_F2FS_FS_LZ4
>> - ret = f2fs_set_lz4hc_level(sbi, name);
>> - if (ret) {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - F2FS_OPTION(sbi).compress_algorithm =
>> - COMPRESS_LZ4;
>> + ret = f2fs_set_lz4hc_level(sbi, name);
>> + if (ret)
>> + return -EINVAL;
>> + F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4;
>> #else
>> - f2fs_info(sbi, "kernel doesn't support lz4 compression");
>> + f2fs_info(sbi, "kernel doesn't support lz4 compression");
>> #endif
>> - } else if (!strncmp(name, "zstd", 4)) {
>> + } else if (!strncmp(name, "zstd", 4)) {
>> #ifdef CONFIG_F2FS_FS_ZSTD
>> - ret = f2fs_set_zstd_level(sbi, name);
>> - if (ret) {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - F2FS_OPTION(sbi).compress_algorithm =
>> - COMPRESS_ZSTD;
>> + ret = f2fs_set_zstd_level(sbi, name);
>> + if (ret)
>> + return -EINVAL;
>> + F2FS_OPTION(sbi).compress_algorithm = COMPRESS_ZSTD;
>> #else
>> - f2fs_info(sbi, "kernel doesn't support zstd compression");
>> + f2fs_info(sbi, "kernel doesn't support zstd compression");
>> #endif
>> - } else if (!strcmp(name, "lzo-rle")) {
>> + } else if (!strcmp(name, "lzo-rle")) {
>> #ifdef CONFIG_F2FS_FS_LZORLE
>> - F2FS_OPTION(sbi).compress_level = 0;
>> - F2FS_OPTION(sbi).compress_algorithm =
>> - COMPRESS_LZORLE;
>> + F2FS_OPTION(sbi).compress_level = 0;
>> + F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZORLE;
>> #else
>> - f2fs_info(sbi, "kernel doesn't support lzorle compression");
>> + f2fs_info(sbi, "kernel doesn't support lzorle compression");
>> #endif
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - kfree(name);
>> + } else
>> + return -EINVAL;
>> + break;
>> + case Opt_compress_log_size:
>> + if (!f2fs_sb_has_compression(sbi)) {
>> + f2fs_info(sbi, "Image doesn't support compression");
>> break;
>> - case Opt_compress_log_size:
>> - if (!f2fs_sb_has_compression(sbi)) {
>> - f2fs_info(sbi, "Image doesn't support compression");
>> - break;
>> - }
>> - if (args->from && match_int(args, &arg))
>> - return -EINVAL;
>> - if (arg < MIN_COMPRESS_LOG_SIZE ||
>> - arg > MAX_COMPRESS_LOG_SIZE) {
>> - f2fs_err(sbi,
>> - "Compress cluster log size is out of range");
>> - return -EINVAL;
>> - }
>> - F2FS_OPTION(sbi).compress_log_size = arg;
>> + }
>> + if (result.uint_32 < MIN_COMPRESS_LOG_SIZE ||
>> + result.uint_32 > MAX_COMPRESS_LOG_SIZE) {
>> + f2fs_err(sbi,
>> + "Compress cluster log size is out of range");
>> + return -EINVAL;
>> + }
>> + F2FS_OPTION(sbi).compress_log_size = result.uint_32;
>> + break;
>> + case Opt_compress_extension:
>> + if (!f2fs_sb_has_compression(sbi)) {
>> + f2fs_info(sbi, "Image doesn't support compression");
>> break;
>> - case Opt_compress_extension:
>> - if (!f2fs_sb_has_compression(sbi)) {
>> - f2fs_info(sbi, "Image doesn't support compression");
>> - break;
>> - }
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> -
>> - ext = F2FS_OPTION(sbi).extensions;
>> - ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt;
>> -
>> - if (strlen(name) >= F2FS_EXTENSION_LEN ||
>> - ext_cnt >= COMPRESS_EXT_NUM) {
>> - f2fs_err(sbi,
>> - "invalid extension length/number");
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> + }
>> + name = param->string;
>> + ext = F2FS_OPTION(sbi).extensions;
>> + ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt;
>>
>> - if (is_compress_extension_exist(sbi, name, true)) {
>> - kfree(name);
>> - break;
>> - }
>> + if (strlen(name) >= F2FS_EXTENSION_LEN ||
>> + ext_cnt >= COMPRESS_EXT_NUM) {
>> + f2fs_err(sbi, "invalid extension length/number");
>> + return -EINVAL;
>> + }
>>
>> - ret = strscpy(ext[ext_cnt], name);
>> - if (ret < 0) {
>> - kfree(name);
>> - return ret;
>> - }
>> - F2FS_OPTION(sbi).compress_ext_cnt++;
>> - kfree(name);
>> + if (is_compress_extension_exist(sbi, name, true))
>> break;
>> - case Opt_nocompress_extension:
>> - if (!f2fs_sb_has_compression(sbi)) {
>> - f2fs_info(sbi, "Image doesn't support compression");
>> - break;
>> - }
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> -
>> - noext = F2FS_OPTION(sbi).noextensions;
>> - noext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt;
>>
>> - if (strlen(name) >= F2FS_EXTENSION_LEN ||
>> - noext_cnt >= COMPRESS_EXT_NUM) {
>> - f2fs_err(sbi,
>> - "invalid extension length/number");
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> + ret = strscpy(ext[ext_cnt], name, F2FS_EXTENSION_LEN);
>> + if (ret < 0)
>> + return ret;
>> + F2FS_OPTION(sbi).compress_ext_cnt++;
>> + break;
>> + case Opt_nocompress_extension:
>> + if (!f2fs_sb_has_compression(sbi)) {
>> + f2fs_info(sbi, "Image doesn't support compression");
>> + break;
>> + }
>> + name = param->string;
>> + noext = F2FS_OPTION(sbi).noextensions;
>> + noext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt;
>>
>> - if (is_compress_extension_exist(sbi, name, false)) {
>> - kfree(name);
>> - break;
>> - }
>> + if (strlen(name) >= F2FS_EXTENSION_LEN ||
>> + noext_cnt >= COMPRESS_EXT_NUM) {
>> + f2fs_err(sbi, "invalid extension length/number");
>> + return -EINVAL;
>> + }
>>
>> - ret = strscpy(noext[noext_cnt], name);
>> - if (ret < 0) {
>> - kfree(name);
>> - return ret;
>> - }
>> - F2FS_OPTION(sbi).nocompress_ext_cnt++;
>> - kfree(name);
>> + if (is_compress_extension_exist(sbi, name, false))
>> break;
>> - case Opt_compress_chksum:
>> - if (!f2fs_sb_has_compression(sbi)) {
>> - f2fs_info(sbi, "Image doesn't support compression");
>> - break;
>> - }
>> - F2FS_OPTION(sbi).compress_chksum = true;
>> +
>> + ret = strscpy(noext[noext_cnt], name, F2FS_EXTENSION_LEN);
>> + if (ret < 0)
>> + return ret;
>> + F2FS_OPTION(sbi).nocompress_ext_cnt++;
>> + break;
>> + case Opt_compress_chksum:
>> + if (!f2fs_sb_has_compression(sbi)) {
>> + f2fs_info(sbi, "Image doesn't support compression");
>> break;
>> - case Opt_compress_mode:
>> - if (!f2fs_sb_has_compression(sbi)) {
>> - f2fs_info(sbi, "Image doesn't support compression");
>> - break;
>> - }
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> - if (!strcmp(name, "fs")) {
>> - F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS;
>> - } else if (!strcmp(name, "user")) {
>> - F2FS_OPTION(sbi).compress_mode = COMPR_MODE_USER;
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - kfree(name);
>> + }
>> + F2FS_OPTION(sbi).compress_chksum = true;
>> + break;
>> + case Opt_compress_mode:
>> + if (!f2fs_sb_has_compression(sbi)) {
>> + f2fs_info(sbi, "Image doesn't support compression");
>> break;
>> - case Opt_compress_cache:
>> - if (!f2fs_sb_has_compression(sbi)) {
>> - f2fs_info(sbi, "Image doesn't support compression");
>> - break;
>> - }
>> - set_opt(sbi, COMPRESS_CACHE);
>> + }
>> + F2FS_OPTION(sbi).compress_mode = result.uint_32;
>> + break;
>> + case Opt_compress_cache:
>> + if (!f2fs_sb_has_compression(sbi)) {
>> + f2fs_info(sbi, "Image doesn't support compression");
>> break;
>> + }
>> + set_opt(sbi, COMPRESS_CACHE);
>> + break;
>> #else
>> - case Opt_compress_algorithm:
>> - case Opt_compress_log_size:
>> - case Opt_compress_extension:
>> - case Opt_nocompress_extension:
>> - case Opt_compress_chksum:
>> - case Opt_compress_mode:
>> - case Opt_compress_cache:
>> - f2fs_info(sbi, "compression options not supported");
>> - break;
>> + case Opt_compress_algorithm:
>> + case Opt_compress_log_size:
>> + case Opt_compress_extension:
>> + case Opt_nocompress_extension:
>> + case Opt_compress_chksum:
>> + case Opt_compress_mode:
>> + case Opt_compress_cache:
>> + f2fs_info(sbi, "compression options not supported");
>> + break;
>> #endif
>> - case Opt_atgc:
>> - set_opt(sbi, ATGC);
>> - break;
>> - case Opt_gc_merge:
>> - set_opt(sbi, GC_MERGE);
>> - break;
>> - case Opt_nogc_merge:
>> + case Opt_atgc:
>> + set_opt(sbi, ATGC);
>> + break;
>> + case Opt_gc_merge:
>> + if (result.negated)
>> clear_opt(sbi, GC_MERGE);
>> - break;
>> - case Opt_discard_unit:
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> - if (!strcmp(name, "block")) {
>> - F2FS_OPTION(sbi).discard_unit =
>> - DISCARD_UNIT_BLOCK;
>> - } else if (!strcmp(name, "segment")) {
>> - F2FS_OPTION(sbi).discard_unit =
>> - DISCARD_UNIT_SEGMENT;
>> - } else if (!strcmp(name, "section")) {
>> - F2FS_OPTION(sbi).discard_unit =
>> - DISCARD_UNIT_SECTION;
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - kfree(name);
>> - break;
>> - case Opt_memory_mode:
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> - if (!strcmp(name, "normal")) {
>> - F2FS_OPTION(sbi).memory_mode =
>> - MEMORY_MODE_NORMAL;
>> - } else if (!strcmp(name, "low")) {
>> - F2FS_OPTION(sbi).memory_mode =
>> - MEMORY_MODE_LOW;
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> - }
>> - kfree(name);
>> - break;
>> - case Opt_age_extent_cache:
>> - set_opt(sbi, AGE_EXTENT_CACHE);
>> - break;
>> - case Opt_errors:
>> - name = match_strdup(&args[0]);
>> - if (!name)
>> - return -ENOMEM;
>> - if (!strcmp(name, "remount-ro")) {
>> - F2FS_OPTION(sbi).errors =
>> - MOUNT_ERRORS_READONLY;
>> - } else if (!strcmp(name, "continue")) {
>> - F2FS_OPTION(sbi).errors =
>> - MOUNT_ERRORS_CONTINUE;
>> - } else if (!strcmp(name, "panic")) {
>> - F2FS_OPTION(sbi).errors =
>> - MOUNT_ERRORS_PANIC;
>> - } else {
>> - kfree(name);
>> - return -EINVAL;
>> + else
>> + set_opt(sbi, GC_MERGE);
>> + break;
>> + case Opt_discard_unit:
>> + F2FS_OPTION(sbi).discard_unit = result.uint_32;
>> + break;
>> + case Opt_memory_mode:
>> + F2FS_OPTION(sbi).memory_mode = result.uint_32;
>> + break;
>> + case Opt_age_extent_cache:
>> + set_opt(sbi, AGE_EXTENT_CACHE);
>> + break;
>> + case Opt_errors:
>> + F2FS_OPTION(sbi).errors = result.uint_32;
>> + break;
>> + case Opt_nat_bits:
>> + set_opt(sbi, NAT_BITS);
>> + break;
>> + }
>> + return 0;
>> +}
>> +
>> +static int parse_options(struct f2fs_sb_info *sbi, char *options, bool is_remount)
>> +{
>> + struct fs_parameter param;
>> + struct fs_context fc;
>> + char *key;
>> + int ret;
>> +
>> + if (!options)
>> + return 0;
>> +
>> + memset(&fc, 0, sizeof(fc));
>> + fc.s_fs_info = sbi;
>> + if (is_remount)
>> + fc.purpose = FS_CONTEXT_FOR_RECONFIGURE;
>> +
>> + while ((key = strsep(&options, ",")) != NULL) {
>> + if (*key) {
>> + size_t v_len = 0;
>> + char *value = strchr(key, '=');
>> +
>> + param.type = fs_value_is_flag;
>> + param.string = NULL;
>> +
>> + if (value) {
>> + if (value == key)
>> + continue;
>> +
>> + *value++ = 0;
>> + v_len = strlen(value);
>> + param.string = kmemdup_nul(value, v_len, GFP_KERNEL);
>> + if (!param.string)
>> + return -ENOMEM;
>> + param.type = fs_value_is_string;
>> }
>> - kfree(name);
>> - break;
>> - case Opt_nat_bits:
>> - set_opt(sbi, NAT_BITS);
>> - break;
>> - default:
>> - f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value",
>> - p);
>> - return -EINVAL;
>> +
>> + param.key = key;
>> + param.size = v_len;
>> +
>> + ret = handle_mount_opt(&fc, ¶m);
>> + kfree(param.string);
>> + if (ret < 0)
>> + return ret;
>> }
>> }
>> return 0;
>> }
>>
>> -static int f2fs_default_check(struct f2fs_sb_info *sbi)
>> +static int f2fs_validate_options(struct f2fs_sb_info *sbi)
>> {
>> #ifdef CONFIG_QUOTA
>> if (f2fs_check_quota_options(sbi))
>> @@ -2527,7 +2285,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>> }
>> #endif
>>
>> - err = f2fs_default_check(sbi);
>> + err = f2fs_validate_options(sbi);
>> if (err)
>> goto restore_opts;
>>
>> @@ -4725,7 +4483,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>> if (err)
>> goto free_options;
>>
>> - err = f2fs_default_check(sbi);
>> + err = f2fs_validate_options(sbi);
>> if (err)
>> goto free_options;
>>
>
next prev parent reply other threads:[~2025-07-07 13:40 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-02 9:02 [PATCH v4 0/7] f2fs: new mount API conversion Hongbo Li
2025-06-02 9:02 ` [PATCH v4 1/7] f2fs: Add fs parameter specifications for mount options Hongbo Li
2025-06-02 9:02 ` [PATCH v4 2/7] f2fs: move the option parser into handle_mount_opt Hongbo Li
2025-07-04 3:27 ` Chao Yu
2025-07-07 13:20 ` Hongbo Li [this message]
2025-07-09 17:48 ` Jaegeuk Kim
2025-07-10 9:25 ` Hongbo Li
2025-06-02 9:02 ` [PATCH v4 3/7] f2fs: Allow sbi to be NULL in f2fs_printk Hongbo Li
2025-06-02 9:02 ` [PATCH v4 4/7] f2fs: Add f2fs_fs_context to record the mount options Hongbo Li
2025-06-02 9:02 ` [PATCH v4 5/7] f2fs: separate the options parsing and options checking Hongbo Li
2025-07-07 12:17 ` Chao Yu
2025-07-08 2:56 ` Hongbo Li
2025-07-10 6:54 ` Chao Yu
2025-06-02 9:02 ` [PATCH v4 6/7] f2fs: introduce fs_context_operation structure Hongbo Li
2025-06-02 9:02 ` [PATCH v4 7/7] f2fs: switch to the new mount api Hongbo Li
2025-06-02 16:05 ` [PATCH v4 0/7] f2fs: new mount API conversion Jaegeuk Kim
2025-06-03 1:09 ` Hongbo Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2601f452-5139-4a1b-8a5c-d305b27364c0@huawei.com \
--to=lihongbo22@huawei.com \
--cc=chao@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=linux-f2fs-devel@lists.sourceforge.net \
--cc=linux-fsdevel@vger.kernel.org \
--cc=sandeen@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).