From: Hongbo Li <lihongb...@huawei.com> At the parsing phase of mouont in the new mount api, options value will be recorded with the context, and then it will be used in fill_super and other helpers.
Note that, this is a temporary status, we want remove the sb and sbi usages in handle_mount_opt. So here the f2fs_fs_context only records the mount options, it will be copied in sb/sbi in later process. (At this point in the series, mount options are temporarily not set during mount.) Signed-off-by: Hongbo Li <lihongb...@huawei.com> [sandeen: forward port, minor fixes and updates] Signed-off-by: Eric Sandeen <sand...@redhat.com> --- fs/f2fs/super.c | 419 ++++++++++++++++++++++++++++-------------------- 1 file changed, 244 insertions(+), 175 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 35190db4501c..15befeb45c94 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -310,8 +310,65 @@ static match_table_t f2fs_checkpoint_tokens = { {Opt_err, NULL}, }; +#define F2FS_SPEC_background_gc (1 << 0) +#define F2FS_SPEC_inline_xattr_size (1 << 1) +#define F2FS_SPEC_active_logs (1 << 2) +#define F2FS_SPEC_reserve_root (1 << 3) +#define F2FS_SPEC_resgid (1 << 4) +#define F2FS_SPEC_resuid (1 << 5) +#define F2FS_SPEC_mode (1 << 6) +#define F2FS_SPEC_fault_injection (1 << 7) +#define F2FS_SPEC_fault_type (1 << 8) +#define F2FS_SPEC_jqfmt (1 << 9) +#define F2FS_SPEC_alloc_mode (1 << 10) +#define F2FS_SPEC_fsync_mode (1 << 11) +#define F2FS_SPEC_checkpoint_disable_cap (1 << 12) +#define F2FS_SPEC_checkpoint_disable_cap_perc (1 << 13) +#define F2FS_SPEC_compress_level (1 << 14) +#define F2FS_SPEC_compress_algorithm (1 << 15) +#define F2FS_SPEC_compress_log_size (1 << 16) +#define F2FS_SPEC_compress_extension (1 << 17) +#define F2FS_SPEC_nocompress_extension (1 << 18) +#define F2FS_SPEC_compress_chksum (1 << 19) +#define F2FS_SPEC_compress_mode (1 << 20) +#define F2FS_SPEC_discard_unit (1 << 21) +#define F2FS_SPEC_memory_mode (1 << 22) +#define F2FS_SPEC_errors (1 << 23) + +struct f2fs_fs_context { + struct f2fs_mount_info info; + unsigned int opt_mask; /* Bits changed */ + unsigned int spec_mask; + unsigned short qname_mask; + unsigned long sflags; + unsigned long sflags_mask; +}; + +#define F2FS_CTX_INFO(ctx) ((ctx)->info) + +static inline void ctx_set_opt(struct f2fs_fs_context *ctx, + unsigned int flag) +{ + ctx->info.opt |= flag; + ctx->opt_mask |= flag; +} + +static inline void ctx_clear_opt(struct f2fs_fs_context *ctx, + unsigned int flag) +{ + ctx->info.opt &= ~flag; + ctx->opt_mask |= flag; +} + +static inline void ctx_set_flags(struct f2fs_fs_context *ctx, + unsigned int flag) +{ + ctx->sflags |= flag; + ctx->sflags_mask |= flag; +} + void f2fs_printk(struct f2fs_sb_info *sbi, bool limit_rate, - const char *fmt, ...) + const char *fmt, ...) { struct va_format vaf; va_list args; @@ -429,57 +486,51 @@ static void init_once(void *foo) #ifdef CONFIG_QUOTA static const char * const quotatypes[] = INITQFNAMES; #define QTYPE2NAME(t) (quotatypes[t]) -static int f2fs_set_qf_name(struct f2fs_sb_info *sbi, int qtype, - struct fs_parameter *param) +/* + * Note the name of the specified quota file. + */ +static int f2fs_note_qf_name(struct fs_context *fc, int qtype, + struct fs_parameter *param) { - struct super_block *sb = sbi->sb; + struct f2fs_fs_context *ctx = fc->fs_private; char *qname; - int ret = -EINVAL; - if (sb_any_quota_loaded(sb) && !F2FS_OPTION(sbi).s_qf_names[qtype]) { - f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); + if (param->size < 1) { + f2fs_err(NULL, "Missing quota name"); return -EINVAL; } - if (f2fs_sb_has_quota_ino(sbi)) { - f2fs_info(sbi, "QUOTA feature is enabled, so ignore qf_name"); + if (strchr(param->string, '/')) { + f2fs_err(NULL, "quotafile must be on filesystem root"); + return -EINVAL; + } + if (ctx->info.s_qf_names[qtype]) { + if (strcmp(ctx->info.s_qf_names[qtype], param->string) != 0) { + f2fs_err(NULL, "Quota file already specified"); + return -EINVAL; + } return 0; } qname = kmemdup_nul(param->string, param->size, GFP_KERNEL); if (!qname) { - f2fs_err(sbi, "Not enough memory for storing quotafile name"); + f2fs_err(NULL, "Not enough memory for storing quotafile name"); return -ENOMEM; } - if (F2FS_OPTION(sbi).s_qf_names[qtype]) { - if (strcmp(F2FS_OPTION(sbi).s_qf_names[qtype], qname) == 0) - ret = 0; - else - f2fs_err(sbi, "%s quota file already specified", - QTYPE2NAME(qtype)); - goto errout; - } - if (strchr(qname, '/')) { - f2fs_err(sbi, "quotafile must be on filesystem root"); - goto errout; - } - F2FS_OPTION(sbi).s_qf_names[qtype] = qname; - set_opt(sbi, QUOTA); + F2FS_CTX_INFO(ctx).s_qf_names[qtype] = qname; + ctx->qname_mask |= 1 << qtype; return 0; -errout: - kfree(qname); - return ret; } -static int f2fs_clear_qf_name(struct f2fs_sb_info *sbi, int qtype) +/* + * Clear the name of the specified quota file. + */ +static int f2fs_unnote_qf_name(struct fs_context *fc, int qtype) { - struct super_block *sb = sbi->sb; + struct f2fs_fs_context *ctx = fc->fs_private; - if (sb_any_quota_loaded(sb) && F2FS_OPTION(sbi).s_qf_names[qtype]) { - f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); - return -EINVAL; - } - kfree(F2FS_OPTION(sbi).s_qf_names[qtype]); - F2FS_OPTION(sbi).s_qf_names[qtype] = NULL; + kfree(ctx->info.s_qf_names[qtype]); + ctx->info.s_qf_names[qtype] = NULL; + ctx->qname_mask |= 1 << qtype; return 0; } @@ -529,54 +580,33 @@ 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 struct fs_parameter *param, - bool is_remount) +static int f2fs_parse_test_dummy_encryption(const struct fs_parameter *param, + struct f2fs_fs_context *ctx) { - struct fscrypt_dummy_policy *policy = - &F2FS_OPTION(sbi).dummy_enc_policy; int err; if (!IS_ENABLED(CONFIG_FS_ENCRYPTION)) { - f2fs_warn(sbi, "test_dummy_encryption option not supported"); + f2fs_warn(NULL, "test_dummy_encryption option not supported"); return -EINVAL; } - - if (!f2fs_sb_has_encrypt(sbi)) { - f2fs_err(sbi, "Encrypt feature is off"); - return -EINVAL; - } - - /* - * This mount option is just for testing, and it's not worthwhile to - * implement the extra complexity (e.g. RCU protection) that would be - * needed to allow it to be set or changed during remount. We do allow - * it to be specified during remount, but only if there is no change. - */ - if (is_remount && !fscrypt_is_dummy_policy_set(policy)) { - f2fs_warn(sbi, "Can't set test_dummy_encryption on remount"); - return -EINVAL; - } - - err = fscrypt_parse_test_dummy_encryption(param, policy); + err = fscrypt_parse_test_dummy_encryption(param, + &ctx->info.dummy_enc_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", + if (err == -EINVAL) + f2fs_warn(NULL, "Value of option \"%s\" is unrecognized", param->key); + else if (err == -EEXIST) + f2fs_warn(NULL, "Conflicting test_dummy_encryption options"); else - f2fs_warn(sbi, "Error processing option \"%s\" [%d]", + f2fs_warn(NULL, "Error processing option \"%s\" [%d]", param->key, err); return -EINVAL; } - f2fs_warn(sbi, "Test dummy encryption mode enabled"); return 0; } #ifdef CONFIG_F2FS_FS_COMPRESSION -static bool is_compress_extension_exist(struct f2fs_sb_info *sbi, +static bool is_compress_extension_exist(struct f2fs_mount_info *info, const char *new_ext, bool is_ext) { unsigned char (*ext)[F2FS_EXTENSION_LEN]; @@ -584,11 +614,11 @@ static bool is_compress_extension_exist(struct f2fs_sb_info *sbi, int i; if (is_ext) { - ext = F2FS_OPTION(sbi).extensions; - ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt; + ext = info->extensions; + ext_cnt = info->compress_ext_cnt; } else { - ext = F2FS_OPTION(sbi).noextensions; - ext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt; + ext = info->noextensions; + ext_cnt = info->nocompress_ext_cnt; } for (i = 0; i < ext_cnt; i++) { @@ -637,58 +667,62 @@ static int f2fs_test_compress_extension(struct f2fs_sb_info *sbi) } #ifdef CONFIG_F2FS_FS_LZ4 -static int f2fs_set_lz4hc_level(struct f2fs_sb_info *sbi, const char *str) +static int f2fs_set_lz4hc_level(struct f2fs_fs_context *ctx, const char *str) { #ifdef CONFIG_F2FS_FS_LZ4HC unsigned int level; if (strlen(str) == 3) { - F2FS_OPTION(sbi).compress_level = 0; + F2FS_CTX_INFO(ctx).compress_level = 0; + ctx->spec_mask |= F2FS_SPEC_compress_level; return 0; } str += 3; if (str[0] != ':') { - f2fs_info(sbi, "wrong format, e.g. <alg_name>:<compr_level>"); + f2fs_info(NULL, "wrong format, e.g. <alg_name>:<compr_level>"); return -EINVAL; } if (kstrtouint(str + 1, 10, &level)) return -EINVAL; if (!f2fs_is_compress_level_valid(COMPRESS_LZ4, level)) { - f2fs_info(sbi, "invalid lz4hc compress level: %d", level); + f2fs_info(NULL, "invalid lz4hc compress level: %d", level); return -EINVAL; } - F2FS_OPTION(sbi).compress_level = level; + F2FS_CTX_INFO(ctx).compress_level = level; + ctx->spec_mask |= F2FS_SPEC_compress_level; return 0; #else if (strlen(str) == 3) { - F2FS_OPTION(sbi).compress_level = 0; + F2FS_CTX_INFO(ctx).compress_level = 0; + ctx->spec_mask |= F2FS_SPEC_compress_level; return 0; } - f2fs_info(sbi, "kernel doesn't support lz4hc compression"); + f2fs_info(NULL, "kernel doesn't support lz4hc compression"); return -EINVAL; #endif } #endif #ifdef CONFIG_F2FS_FS_ZSTD -static int f2fs_set_zstd_level(struct f2fs_sb_info *sbi, const char *str) +static int f2fs_set_zstd_level(struct f2fs_fs_context *ctx, const char *str) { int level; int len = 4; if (strlen(str) == len) { - F2FS_OPTION(sbi).compress_level = F2FS_ZSTD_DEFAULT_CLEVEL; + F2FS_CTX_INFO(ctx).compress_level = F2FS_ZSTD_DEFAULT_CLEVEL; + ctx->spec_mask |= F2FS_SPEC_compress_level; return 0; } str += len; if (str[0] != ':') { - f2fs_info(sbi, "wrong format, e.g. <alg_name>:<compr_level>"); + f2fs_info(NULL, "wrong format, e.g. <alg_name>:<compr_level>"); return -EINVAL; } if (kstrtoint(str + 1, 10, &level)) @@ -696,16 +730,17 @@ static int f2fs_set_zstd_level(struct f2fs_sb_info *sbi, const char *str) /* f2fs does not support negative compress level now */ if (level < 0) { - f2fs_info(sbi, "do not support negative compress level: %d", level); + f2fs_info(NULL, "do not support negative compress level: %d", level); return -ERANGE; } if (!f2fs_is_compress_level_valid(COMPRESS_ZSTD, level)) { - f2fs_info(sbi, "invalid zstd compress level: %d", level); + f2fs_info(NULL, "invalid zstd compress level: %d", level); return -EINVAL; } - F2FS_OPTION(sbi).compress_level = level; + F2FS_CTX_INFO(ctx).compress_level = level; + ctx->spec_mask |= F2FS_SPEC_compress_level; return 0; } #endif @@ -713,6 +748,7 @@ static int f2fs_set_zstd_level(struct f2fs_sb_info *sbi, const char *str) static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) { + struct f2fs_fs_context *ctx = fc->fs_private; struct f2fs_sb_info *sbi = fc->s_fs_info; #ifdef CONFIG_F2FS_FS_COMPRESSION unsigned char (*ext)[F2FS_EXTENSION_LEN]; @@ -733,14 +769,15 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) switch (token) { case Opt_gc_background: - F2FS_OPTION(sbi).bggc_mode = result.uint_32; + F2FS_CTX_INFO(ctx).bggc_mode = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_background_gc; break; case Opt_disable_roll_forward: - set_opt(sbi, DISABLE_ROLL_FORWARD); + ctx_set_opt(ctx, F2FS_MOUNT_DISABLE_ROLL_FORWARD); break; case Opt_norecovery: /* requires ro mount, checked in f2fs_validate_options */ - set_opt(sbi, NORECOVERY); + ctx_set_opt(ctx, F2FS_MOUNT_NORECOVERY); break; case Opt_discard: if (result.negated) { @@ -748,13 +785,13 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) f2fs_warn(NULL, "discard is required for zoned block devices"); return -EINVAL; } - clear_opt(sbi, DISCARD); + ctx_clear_opt(ctx, F2FS_MOUNT_DISCARD); } else { if (!f2fs_hw_support_discard(sbi)) { f2fs_warn(NULL, "device does not support discard"); break; } - set_opt(sbi, DISCARD); + ctx_set_opt(ctx, F2FS_MOUNT_DISCARD); } break; case Opt_noheap: @@ -764,19 +801,20 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) #ifdef CONFIG_F2FS_FS_XATTR case Opt_user_xattr: if (result.negated) - clear_opt(sbi, XATTR_USER); + ctx_clear_opt(ctx, F2FS_MOUNT_XATTR_USER); else - set_opt(sbi, XATTR_USER); + ctx_set_opt(ctx, F2FS_MOUNT_XATTR_USER); break; case Opt_inline_xattr: if (result.negated) - clear_opt(sbi, INLINE_XATTR); + ctx_clear_opt(ctx, F2FS_MOUNT_INLINE_XATTR); else - set_opt(sbi, INLINE_XATTR); + ctx_set_opt(ctx, F2FS_MOUNT_INLINE_XATTR); break; case Opt_inline_xattr_size: - set_opt(sbi, INLINE_XATTR_SIZE); - F2FS_OPTION(sbi).inline_xattr_size = result.int_32; + ctx_set_opt(ctx, F2FS_MOUNT_INLINE_XATTR_SIZE); + F2FS_CTX_INFO(ctx).inline_xattr_size = result.int_32; + ctx->spec_mask |= F2FS_SPEC_inline_xattr_size; break; #else case Opt_user_xattr: @@ -788,9 +826,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) #ifdef CONFIG_F2FS_FS_POSIX_ACL case Opt_acl: if (result.negated) - clear_opt(sbi, POSIX_ACL); + ctx_clear_opt(ctx, F2FS_MOUNT_POSIX_ACL); else - set_opt(sbi, POSIX_ACL); + ctx_set_opt(ctx, F2FS_MOUNT_POSIX_ACL); break; #else case Opt_acl: @@ -801,37 +839,38 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) 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; + ctx->spec_mask |= F2FS_SPEC_active_logs; + F2FS_CTX_INFO(ctx).active_logs = result.int_32; break; case Opt_disable_ext_identify: - set_opt(sbi, DISABLE_EXT_IDENTIFY); + ctx_set_opt(ctx, F2FS_MOUNT_DISABLE_EXT_IDENTIFY); break; case Opt_inline_data: if (result.negated) - clear_opt(sbi, INLINE_DATA); + ctx_clear_opt(ctx, F2FS_MOUNT_INLINE_DATA); else - set_opt(sbi, INLINE_DATA); + ctx_set_opt(ctx, F2FS_MOUNT_INLINE_DATA); break; case Opt_inline_dentry: if (result.negated) - clear_opt(sbi, INLINE_DENTRY); + ctx_clear_opt(ctx, F2FS_MOUNT_INLINE_DENTRY); else - set_opt(sbi, INLINE_DENTRY); + ctx_set_opt(ctx, F2FS_MOUNT_INLINE_DENTRY); break; case Opt_flush_merge: if (result.negated) - clear_opt(sbi, FLUSH_MERGE); + ctx_clear_opt(ctx, F2FS_MOUNT_FLUSH_MERGE); else - set_opt(sbi, FLUSH_MERGE); + ctx_set_opt(ctx, F2FS_MOUNT_FLUSH_MERGE); break; case Opt_barrier: if (result.negated) - set_opt(sbi, NOBARRIER); + ctx_set_opt(ctx, F2FS_MOUNT_NOBARRIER); else - clear_opt(sbi, NOBARRIER); + ctx_clear_opt(ctx, F2FS_MOUNT_NOBARRIER); break; case Opt_fastboot: - set_opt(sbi, FASTBOOT); + ctx_set_opt(ctx, F2FS_MOUNT_FASTBOOT); break; case Opt_extent_cache: if (result.negated) { @@ -839,42 +878,50 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) f2fs_err(sbi, "device aliasing requires extent cache"); return -EINVAL; } - clear_opt(sbi, READ_EXTENT_CACHE); + ctx_clear_opt(ctx, F2FS_MOUNT_READ_EXTENT_CACHE); } else - set_opt(sbi, READ_EXTENT_CACHE); + ctx_set_opt(ctx, F2FS_MOUNT_READ_EXTENT_CACHE); break; case Opt_data_flush: - set_opt(sbi, DATA_FLUSH); + ctx_set_opt(ctx, F2FS_MOUNT_DATA_FLUSH); break; case Opt_reserve_root: if (test_opt(sbi, RESERVE_ROOT)) { f2fs_info(NULL, "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); + ctx_set_opt(ctx, F2FS_MOUNT_RESERVE_ROOT); + F2FS_CTX_INFO(ctx).root_reserved_blocks = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_reserve_root; } break; case Opt_resuid: - F2FS_OPTION(sbi).s_resuid = result.uid; + F2FS_CTX_INFO(ctx).s_resuid = result.uid; + ctx->spec_mask |= F2FS_SPEC_resuid; break; case Opt_resgid: - F2FS_OPTION(sbi).s_resgid = result.gid; + F2FS_CTX_INFO(ctx).s_resgid = result.gid; + ctx->spec_mask |= F2FS_SPEC_resgid; break; case Opt_mode: - F2FS_OPTION(sbi).fs_mode = result.uint_32; + F2FS_CTX_INFO(ctx).fs_mode = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_mode; break; #ifdef CONFIG_F2FS_FAULT_INJECTION case Opt_fault_injection: if (f2fs_build_fault_attr(sbi, result.int_32, 0, FAULT_RATE)) return -EINVAL; - set_opt(sbi, FAULT_INJECTION); + F2FS_CTX_INFO(ctx).fault_info.inject_rate = result.int_32; + ctx->spec_mask |= F2FS_SPEC_fault_injection; + ctx_set_opt(ctx, F2FS_MOUNT_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); + F2FS_CTX_INFO(ctx).fault_info.inject_type = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_fault_type; + ctx_set_opt(ctx, F2FS_MOUNT_FAULT_INJECTION); break; #else case Opt_fault_injection: @@ -884,55 +931,56 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) #endif case Opt_lazytime: if (result.negated) - clear_opt(sbi, LAZYTIME); + ctx_clear_opt(ctx, F2FS_MOUNT_LAZYTIME); else - set_opt(sbi, LAZYTIME); + ctx_set_opt(ctx, F2FS_MOUNT_LAZYTIME); break; #ifdef CONFIG_QUOTA case Opt_quota: if (result.negated) { - clear_opt(sbi, QUOTA); - clear_opt(sbi, USRQUOTA); - clear_opt(sbi, GRPQUOTA); - clear_opt(sbi, PRJQUOTA); + ctx_clear_opt(ctx, F2FS_MOUNT_QUOTA); + ctx_clear_opt(ctx, F2FS_MOUNT_USRQUOTA); + ctx_clear_opt(ctx, F2FS_MOUNT_GRPQUOTA); + ctx_clear_opt(ctx, F2FS_MOUNT_PRJQUOTA); } else - set_opt(sbi, USRQUOTA); + ctx_set_opt(ctx, F2FS_MOUNT_USRQUOTA); break; case Opt_usrquota: - set_opt(sbi, USRQUOTA); + ctx_set_opt(ctx, F2FS_MOUNT_USRQUOTA); break; case Opt_grpquota: - set_opt(sbi, GRPQUOTA); + ctx_set_opt(ctx, F2FS_MOUNT_GRPQUOTA); break; case Opt_prjquota: - set_opt(sbi, PRJQUOTA); + ctx_set_opt(ctx, F2FS_MOUNT_PRJQUOTA); break; case Opt_usrjquota: if (!*param->string) - ret = f2fs_clear_qf_name(sbi, USRQUOTA); + ret = f2fs_unnote_qf_name(fc, USRQUOTA); else - ret = f2fs_set_qf_name(sbi, USRQUOTA, param); + ret = f2fs_note_qf_name(fc, USRQUOTA, param); if (ret) return ret; break; case Opt_grpjquota: if (!*param->string) - ret = f2fs_clear_qf_name(sbi, GRPQUOTA); + ret = f2fs_unnote_qf_name(fc, GRPQUOTA); else - ret = f2fs_set_qf_name(sbi, GRPQUOTA, param); + ret = f2fs_note_qf_name(fc, GRPQUOTA, param); if (ret) return ret; break; case Opt_prjjquota: if (!*param->string) - ret = f2fs_clear_qf_name(sbi, PRJQUOTA); + ret = f2fs_unnote_qf_name(fc, PRJQUOTA); else - ret = f2fs_set_qf_name(sbi, PRJQUOTA, param); + ret = f2fs_note_qf_name(fc, PRJQUOTA, param); if (ret) return ret; break; case Opt_jqfmt: - F2FS_OPTION(sbi).s_jquota_fmt = result.uint_32; + F2FS_CTX_INFO(ctx).s_jquota_fmt = result.int_32; + ctx->spec_mask |= F2FS_SPEC_jqfmt; break; #else case Opt_quota: @@ -946,19 +994,21 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) break; #endif case Opt_alloc: - F2FS_OPTION(sbi).alloc_mode = result.uint_32; + F2FS_CTX_INFO(ctx).alloc_mode = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_alloc_mode; break; case Opt_fsync: - F2FS_OPTION(sbi).fsync_mode = result.uint_32; + F2FS_CTX_INFO(ctx).fsync_mode = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_fsync_mode; break; case Opt_test_dummy_encryption: - ret = f2fs_set_test_dummy_encryption(sbi, param, is_remount); + ret = f2fs_parse_test_dummy_encryption(param, ctx); if (ret) return ret; break; case Opt_inlinecrypt: #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT - set_opt(sbi, INLINECRYPT); + ctx_set_opt(ctx, F2FS_MOUNT_INLINECRYPT); #else f2fs_info(NULL, "inline encryption not supported"); #endif @@ -972,20 +1022,22 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) return -EINVAL; if (arg < 0 || arg > 100) return -EINVAL; - F2FS_OPTION(sbi).unusable_cap_perc = arg; - set_opt(sbi, DISABLE_CHECKPOINT); + F2FS_CTX_INFO(ctx).unusable_cap_perc = arg; + ctx->spec_mask |= F2FS_SPEC_checkpoint_disable_cap_perc; + ctx_set_opt(ctx, F2FS_MOUNT_DISABLE_CHECKPOINT); break; case Opt_checkpoint_disable_cap: if (args->from && match_int(args, &arg)) return -EINVAL; - F2FS_OPTION(sbi).unusable_cap = arg; - set_opt(sbi, DISABLE_CHECKPOINT); + F2FS_CTX_INFO(ctx).unusable_cap = arg; + ctx->spec_mask |= F2FS_SPEC_checkpoint_disable_cap; + ctx_set_opt(ctx, F2FS_MOUNT_DISABLE_CHECKPOINT); break; case Opt_checkpoint_disable: - set_opt(sbi, DISABLE_CHECKPOINT); + ctx_set_opt(ctx, F2FS_MOUNT_DISABLE_CHECKPOINT); break; case Opt_checkpoint_enable: - clear_opt(sbi, DISABLE_CHECKPOINT); + ctx_clear_opt(ctx, F2FS_MOUNT_DISABLE_CHECKPOINT); break; default: return -EINVAL; @@ -993,9 +1045,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) break; case Opt_checkpoint_merge: if (result.negated) - clear_opt(sbi, MERGE_CHECKPOINT); + ctx_clear_opt(ctx, F2FS_MOUNT_MERGE_CHECKPOINT); else - set_opt(sbi, MERGE_CHECKPOINT); + ctx_set_opt(ctx, F2FS_MOUNT_MERGE_CHECKPOINT); break; #ifdef CONFIG_F2FS_FS_COMPRESSION case Opt_compress_algorithm: @@ -1006,33 +1058,39 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) 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_CTX_INFO(ctx).compress_level = 0; + F2FS_CTX_INFO(ctx).compress_algorithm = COMPRESS_LZO; + ctx->spec_mask |= F2FS_SPEC_compress_level; + ctx->spec_mask |= F2FS_SPEC_compress_algorithm; #else f2fs_info(NULL, "kernel doesn't support lzo compression"); #endif } else if (!strncmp(name, "lz4", 3)) { #ifdef CONFIG_F2FS_FS_LZ4 - ret = f2fs_set_lz4hc_level(sbi, name); + ret = f2fs_set_lz4hc_level(ctx, name); if (ret) return -EINVAL; - F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4; + F2FS_CTX_INFO(ctx).compress_algorithm = COMPRESS_LZ4; + ctx->spec_mask |= F2FS_SPEC_compress_algorithm; #else f2fs_info(NULL, "kernel doesn't support lz4 compression"); #endif } else if (!strncmp(name, "zstd", 4)) { #ifdef CONFIG_F2FS_FS_ZSTD - ret = f2fs_set_zstd_level(sbi, name); + ret = f2fs_set_zstd_level(ctx, name); if (ret) return -EINVAL; - F2FS_OPTION(sbi).compress_algorithm = COMPRESS_ZSTD; + F2FS_CTX_INFO(ctx).compress_algorithm = COMPRESS_ZSTD; + ctx->spec_mask |= F2FS_SPEC_compress_algorithm; #else f2fs_info(NULL, "kernel doesn't support zstd compression"); #endif } 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_CTX_INFO(ctx).compress_level = 0; + F2FS_CTX_INFO(ctx).compress_algorithm = COMPRESS_LZORLE; + ctx->spec_mask |= F2FS_SPEC_compress_level; + ctx->spec_mask |= F2FS_SPEC_compress_algorithm; #else f2fs_info(NULL, "kernel doesn't support lzorle compression"); #endif @@ -1050,7 +1108,8 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) "Compress cluster log size is out of range"); return -EINVAL; } - F2FS_OPTION(sbi).compress_log_size = result.uint_32; + F2FS_CTX_INFO(ctx).compress_log_size = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_compress_log_size; break; case Opt_compress_extension: if (!f2fs_sb_has_compression(sbi)) { @@ -1058,8 +1117,8 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) break; } name = param->string; - ext = F2FS_OPTION(sbi).extensions; - ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt; + ext = F2FS_CTX_INFO(ctx).extensions; + ext_cnt = F2FS_CTX_INFO(ctx).compress_ext_cnt; if (strlen(name) >= F2FS_EXTENSION_LEN || ext_cnt >= COMPRESS_EXT_NUM) { @@ -1067,13 +1126,14 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) return -EINVAL; } - if (is_compress_extension_exist(sbi, name, true)) + if (is_compress_extension_exist(&ctx->info, name, true)) break; ret = strscpy(ext[ext_cnt], name, F2FS_EXTENSION_LEN); if (ret < 0) return ret; - F2FS_OPTION(sbi).compress_ext_cnt++; + F2FS_CTX_INFO(ctx).compress_ext_cnt++; + ctx->spec_mask |= F2FS_SPEC_compress_extension; break; case Opt_nocompress_extension: if (!f2fs_sb_has_compression(sbi)) { @@ -1081,8 +1141,8 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) break; } name = param->string; - noext = F2FS_OPTION(sbi).noextensions; - noext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt; + noext = F2FS_CTX_INFO(ctx).noextensions; + noext_cnt = F2FS_CTX_INFO(ctx).nocompress_ext_cnt; if (strlen(name) >= F2FS_EXTENSION_LEN || noext_cnt >= COMPRESS_EXT_NUM) { @@ -1090,34 +1150,37 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) return -EINVAL; } - if (is_compress_extension_exist(sbi, name, false)) + if (is_compress_extension_exist(&ctx->info, name, false)) break; ret = strscpy(noext[noext_cnt], name, F2FS_EXTENSION_LEN); if (ret < 0) return ret; - F2FS_OPTION(sbi).nocompress_ext_cnt++; + F2FS_CTX_INFO(ctx).nocompress_ext_cnt++; + ctx->spec_mask |= F2FS_SPEC_nocompress_extension; break; case Opt_compress_chksum: if (!f2fs_sb_has_compression(sbi)) { f2fs_info(NULL, "Image doesn't support compression"); break; } - F2FS_OPTION(sbi).compress_chksum = true; + F2FS_CTX_INFO(ctx).compress_chksum = true; + ctx->spec_mask |= F2FS_SPEC_compress_chksum; break; case Opt_compress_mode: if (!f2fs_sb_has_compression(sbi)) { f2fs_info(NULL, "Image doesn't support compression"); break; } - F2FS_OPTION(sbi).compress_mode = result.uint_32; + F2FS_CTX_INFO(ctx).compress_mode = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_compress_mode; break; case Opt_compress_cache: if (!f2fs_sb_has_compression(sbi)) { f2fs_info(NULL, "Image doesn't support compression"); break; } - set_opt(sbi, COMPRESS_CACHE); + ctx_set_opt(ctx, F2FS_MOUNT_COMPRESS_CACHE); break; #else case Opt_compress_algorithm: @@ -1131,28 +1194,31 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param) break; #endif case Opt_atgc: - set_opt(sbi, ATGC); + ctx_set_opt(ctx, F2FS_MOUNT_ATGC); break; case Opt_gc_merge: if (result.negated) - clear_opt(sbi, GC_MERGE); + ctx_clear_opt(ctx, F2FS_MOUNT_GC_MERGE); else - set_opt(sbi, GC_MERGE); + ctx_set_opt(ctx, F2FS_MOUNT_GC_MERGE); break; case Opt_discard_unit: - F2FS_OPTION(sbi).discard_unit = result.uint_32; + F2FS_CTX_INFO(ctx).discard_unit = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_discard_unit; break; case Opt_memory_mode: - F2FS_OPTION(sbi).memory_mode = result.uint_32; + F2FS_CTX_INFO(ctx).memory_mode = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_memory_mode; break; case Opt_age_extent_cache: - set_opt(sbi, AGE_EXTENT_CACHE); + ctx_set_opt(ctx, F2FS_MOUNT_AGE_EXTENT_CACHE); break; case Opt_errors: - F2FS_OPTION(sbi).errors = result.uint_32; + F2FS_CTX_INFO(ctx).errors = result.uint_32; + ctx->spec_mask |= F2FS_SPEC_errors; break; case Opt_nat_bits: - set_opt(sbi, NAT_BITS); + ctx_set_opt(ctx, F2FS_MOUNT_NAT_BITS); break; } return 0; @@ -1162,6 +1228,7 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options, bool is_remoun { struct fs_parameter param; struct fs_context fc; + struct f2fs_fs_context ctx; char *key; int ret; @@ -1170,6 +1237,8 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options, bool is_remoun memset(&fc, 0, sizeof(fc)); fc.s_fs_info = sbi; + fc.fs_private = &ctx; + if (is_remount) fc.purpose = FS_CONTEXT_FOR_RECONFIGURE; -- 2.49.0 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel