Commit c9d35ee0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'merge.nfs-fs_parse.1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs file system parameter updates from Al Viro:
 "Saner fs_parser.c guts and data structures. The system-wide registry
  of syntax types (string/enum/int32/oct32/.../etc.) is gone and so is
  the horror switch() in fs_parse() that would have to grow another case
  every time something got added to that system-wide registry.

  New syntax types can be added by filesystems easily now, and their
  namespace is that of functions - not of system-wide enum members. IOW,
  they can be shared or kept private and if some turn out to be widely
  useful, we can make them common library helpers, etc., without having
  to do anything whatsoever to fs_parse() itself.

  And we already get that kind of requests - the thing that finally
  pushed me into doing that was "oh, and let's add one for timeouts -
  things like 15s or 2h". If some filesystem really wants that, let them
  do it. Without somebody having to play gatekeeper for the variants
  blessed by direct support in fs_parse(), TYVM.

  Quite a bit of boilerplate is gone. And IMO the data structures make a
  lot more sense now. -200LoC, while we are at it"

* 'merge.nfs-fs_parse.1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (25 commits)
  tmpfs: switch to use of invalfc()
  cgroup1: switch to use of errorfc() et.al.
  procfs: switch to use of invalfc()
  hugetlbfs: switch to use of invalfc()
  cramfs: switch to use of errofc() et.al.
  gfs2: switch to use of errorfc() et.al.
  fuse: switch to use errorfc() et.al.
  ceph: use errorfc() and friends instead of spelling the prefix out
  prefix-handling analogues of errorf() and friends
  turn fs_param_is_... into functions
  fs_parse: handle optional arguments sanely
  fs_parse: fold fs_parameter_desc/fs_parameter_spec
  fs_parser: remove fs_parameter_description name field
  add prefix to fs_context->log
  ceph_parse_param(), ceph_parse_mon_ips(): switch to passing fc_log
  new primitive: __fs_parse()
  switch rbd and libceph to p_log-based primitives
  struct p_log, variants of warnf() et.al. taking that one instead
  teach logfc() to handle prefices, give it saner calling conventions
  get rid of cg_invalf()
  ...
parents 236f4532 f35aa2bc
......@@ -427,7 +427,6 @@ returned.
fs_value_is_string, Value is a string
fs_value_is_blob, Value is a binary blob
fs_value_is_filename, Value is a filename* + dirfd
fs_value_is_filename_empty, Value is a filename* + dirfd + AT_EMPTY_PATH
fs_value_is_file, Value is an open file (file*)
If there is a value, that value is stored in a union in the struct in one
......@@ -519,7 +518,6 @@ Parameters are described using structures defined in linux/fs_parser.h.
There's a core description struct that links everything together:
struct fs_parameter_description {
const char name[16];
const struct fs_parameter_spec *specs;
const struct fs_parameter_enum *enums;
};
......@@ -535,19 +533,13 @@ For example:
};
static const struct fs_parameter_description afs_fs_parameters = {
.name = "kAFS",
.specs = afs_param_specs,
.enums = afs_param_enums,
};
The members are as follows:
(1) const char name[16];
The name to be used in error messages generated by the parse helper
functions.
(2) const struct fs_parameter_specification *specs;
(1) const struct fs_parameter_specification *specs;
Table of parameter specifications, terminated with a null entry, where the
entries are of type:
......@@ -626,7 +618,7 @@ The members are as follows:
of arguments to specify the type and the flags for anything that doesn't
match one of the above macros.
(6) const struct fs_parameter_enum *enums;
(2) const struct fs_parameter_enum *enums;
Table of enum value names to integer mappings, terminated with a null
entry. This is of type:
......
......@@ -583,7 +583,7 @@ enum {
Opt_uid, Opt_gid, Opt_mode, Opt_debug,
};
static const struct fs_parameter_spec spufs_param_specs[] = {
static const struct fs_parameter_spec spufs_fs_parameters[] = {
fsparam_u32 ("gid", Opt_gid),
fsparam_u32oct ("mode", Opt_mode),
fsparam_u32 ("uid", Opt_uid),
......@@ -591,11 +591,6 @@ static const struct fs_parameter_spec spufs_param_specs[] = {
{}
};
static const struct fs_parameter_description spufs_fs_parameters = {
.name = "spufs",
.specs = spufs_param_specs,
};
static int spufs_show_options(struct seq_file *m, struct dentry *root)
{
struct spufs_sb_info *sbi = spufs_get_sb_info(root->d_sb);
......@@ -623,7 +618,7 @@ static int spufs_parse_param(struct fs_context *fc, struct fs_parameter *param)
kgid_t gid;
int opt;
opt = fs_parse(fc, &spufs_fs_parameters, param, &result);
opt = fs_parse(fc, spufs_fs_parameters, param, &result);
if (opt < 0)
return opt;
......@@ -774,7 +769,7 @@ static struct file_system_type spufs_type = {
.owner = THIS_MODULE,
.name = "spufs",
.init_fs_context = spufs_init_fs_context,
.parameters = &spufs_fs_parameters,
.parameters = spufs_fs_parameters,
.kill_sb = kill_litter_super,
};
MODULE_ALIAS_FS("spufs");
......
......@@ -209,17 +209,12 @@ static int hypfs_release(struct inode *inode, struct file *filp)
enum { Opt_uid, Opt_gid, };
static const struct fs_parameter_spec hypfs_param_specs[] = {
static const struct fs_parameter_spec hypfs_fs_parameters[] = {
fsparam_u32("gid", Opt_gid),
fsparam_u32("uid", Opt_uid),
{}
};
static const struct fs_parameter_description hypfs_fs_parameters = {
.name = "hypfs",
.specs = hypfs_param_specs,
};
static int hypfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct hypfs_sb_info *hypfs_info = fc->s_fs_info;
......@@ -228,7 +223,7 @@ static int hypfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
kgid_t gid;
int opt;
opt = fs_parse(fc, &hypfs_fs_parameters, param, &result);
opt = fs_parse(fc, hypfs_fs_parameters, param, &result);
if (opt < 0)
return opt;
......@@ -455,7 +450,7 @@ static struct file_system_type hypfs_type = {
.owner = THIS_MODULE,
.name = "s390_hypfs",
.init_fs_context = hypfs_init_fs_context,
.parameters = &hypfs_fs_parameters,
.parameters = hypfs_fs_parameters,
.kill_sb = hypfs_kill_super
};
......
......@@ -2127,25 +2127,20 @@ enum rdt_param {
nr__rdt_params
};
static const struct fs_parameter_spec rdt_param_specs[] = {
static const struct fs_parameter_spec rdt_fs_parameters[] = {
fsparam_flag("cdp", Opt_cdp),
fsparam_flag("cdpl2", Opt_cdpl2),
fsparam_flag("mba_MBps", Opt_mba_mbps),
{}
};
static const struct fs_parameter_description rdt_fs_parameters = {
.name = "rdt",
.specs = rdt_param_specs,
};
static int rdt_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct rdt_fs_context *ctx = rdt_fc2context(fc);
struct fs_parse_result result;
int opt;
opt = fs_parse(fc, &rdt_fs_parameters, param, &result);
opt = fs_parse(fc, rdt_fs_parameters, param, &result);
if (opt < 0)
return opt;
......@@ -2378,7 +2373,7 @@ static void rdt_kill_sb(struct super_block *sb)
static struct file_system_type rdt_fs_type = {
.name = "resctrl",
.init_fs_context = rdt_init_fs_context,
.parameters = &rdt_fs_parameters,
.parameters = rdt_fs_parameters,
.kill_sb = rdt_kill_sb,
};
......
......@@ -67,10 +67,10 @@ static struct file_system_type internal_fs_type = {
.name = "devtmpfs",
#ifdef CONFIG_TMPFS
.init_fs_context = shmem_init_fs_context,
.parameters = &shmem_fs_parameters,
.parameters = shmem_fs_parameters,
#else
.init_fs_context = ramfs_init_fs_context,
.parameters = &ramfs_fs_parameters,
.parameters = ramfs_fs_parameters,
#endif
.kill_sb = kill_litter_super,
};
......
......@@ -848,7 +848,7 @@ enum {
Opt_notrim,
};
static const struct fs_parameter_spec rbd_param_specs[] = {
static const struct fs_parameter_spec rbd_parameters[] = {
fsparam_u32 ("alloc_size", Opt_alloc_size),
fsparam_flag ("exclusive", Opt_exclusive),
fsparam_flag ("lock_on_read", Opt_lock_on_read),
......@@ -863,11 +863,6 @@ static const struct fs_parameter_spec rbd_param_specs[] = {
{}
};
static const struct fs_parameter_description rbd_parameters = {
.name = "rbd",
.specs = rbd_param_specs,
};
struct rbd_options {
int queue_depth;
int alloc_size;
......@@ -6353,19 +6348,19 @@ static int rbd_parse_param(struct fs_parameter *param,
{
struct rbd_options *opt = pctx->opts;
struct fs_parse_result result;
struct p_log log = {.prefix = "rbd"};
int token, ret;
ret = ceph_parse_param(param, pctx->copts, NULL);
if (ret != -ENOPARAM)
return ret;
token = fs_parse(NULL, &rbd_parameters, param, &result);
token = __fs_parse(&log, rbd_parameters, param, &result);
dout("%s fs_parse '%s' token %d\n", __func__, param->key, token);
if (token < 0) {
if (token == -ENOPARAM) {
return invalf(NULL, "rbd: Unknown parameter '%s'",
param->key);
}
if (token == -ENOPARAM)
return inval_plog(&log, "Unknown parameter '%s'",
param->key);
return token;
}
......@@ -6378,9 +6373,8 @@ static int rbd_parse_param(struct fs_parameter *param,
case Opt_alloc_size:
if (result.uint_32 < SECTOR_SIZE)
goto out_of_range;
if (!is_power_of_2(result.uint_32)) {
return invalf(NULL, "rbd: alloc_size must be a power of 2");
}
if (!is_power_of_2(result.uint_32))
return inval_plog(&log, "alloc_size must be a power of 2");
opt->alloc_size = result.uint_32;
break;
case Opt_lock_timeout:
......@@ -6416,7 +6410,7 @@ static int rbd_parse_param(struct fs_parameter *param,
return 0;
out_of_range:
return invalf(NULL, "rbd: %s out of range", param->key);
return inval_plog(&log, "%s out of range", param->key);
}
/*
......@@ -6433,7 +6427,7 @@ static int rbd_parse_options(char *options, struct rbd_parse_opts_ctx *pctx)
if (*key) {
struct fs_parameter param = {
.key = key,
.type = fs_value_is_string,
.type = fs_value_is_flag,
};
char *value = strchr(key, '=');
size_t v_len = 0;
......@@ -6443,14 +6437,11 @@ static int rbd_parse_options(char *options, struct rbd_parse_opts_ctx *pctx)
continue;
*value++ = 0;
v_len = strlen(value);
}
if (v_len > 0) {
param.string = kmemdup_nul(value, v_len,
GFP_KERNEL);
if (!param.string)
return -ENOMEM;
param.type = fs_value_is_string;
}
param.size = v_len;
......
......@@ -1488,7 +1488,7 @@ enum {
Opt_gid,
};
static const struct fs_parameter_spec ffs_fs_param_specs[] = {
static const struct fs_parameter_spec ffs_fs_fs_parameters[] = {
fsparam_bool ("no_disconnect", Opt_no_disconnect),
fsparam_u32 ("rmode", Opt_rmode),
fsparam_u32 ("fmode", Opt_fmode),
......@@ -1498,11 +1498,6 @@ static const struct fs_parameter_spec ffs_fs_param_specs[] = {
{}
};
static const struct fs_parameter_description ffs_fs_fs_parameters = {
.name = "kAFS",
.specs = ffs_fs_param_specs,
};
static int ffs_fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct ffs_sb_fill_data *data = fc->fs_private;
......@@ -1511,7 +1506,7 @@ static int ffs_fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
ENTER();
opt = fs_parse(fc, &ffs_fs_fs_parameters, param, &result);
opt = fs_parse(fc, ffs_fs_fs_parameters, param, &result);
if (opt < 0)
return opt;
......@@ -1643,7 +1638,7 @@ static struct file_system_type ffs_fs_type = {
.owner = THIS_MODULE,
.name = "functionfs",
.init_fs_context = ffs_fs_init_fs_context,
.parameters = &ffs_fs_fs_parameters,
.parameters = ffs_fs_fs_parameters,
.kill_sb = ffs_fs_kill_sb,
};
MODULE_ALIAS_FS("functionfs");
......
......@@ -38,13 +38,13 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
static int afs_show_devname(struct seq_file *m, struct dentry *root);
static int afs_show_options(struct seq_file *m, struct dentry *root);
static int afs_init_fs_context(struct fs_context *fc);
static const struct fs_parameter_description afs_fs_parameters;
static const struct fs_parameter_spec afs_fs_parameters[];
struct file_system_type afs_fs_type = {
.owner = THIS_MODULE,
.name = "afs",
.init_fs_context = afs_init_fs_context,
.parameters = &afs_fs_parameters,
.parameters = afs_fs_parameters,
.kill_sb = afs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE,
};
......@@ -73,28 +73,22 @@ enum afs_param {
Opt_source,
};
static const struct fs_parameter_spec afs_param_specs[] = {
fsparam_flag ("autocell", Opt_autocell),
fsparam_flag ("dyn", Opt_dyn),
fsparam_enum ("flock", Opt_flock),
fsparam_string("source", Opt_source),
static const struct constant_table afs_param_flock[] = {
{"local", afs_flock_mode_local },
{"openafs", afs_flock_mode_openafs },
{"strict", afs_flock_mode_strict },
{"write", afs_flock_mode_write },
{}
};
static const struct fs_parameter_enum afs_param_enums[] = {
{ Opt_flock, "local", afs_flock_mode_local },
{ Opt_flock, "openafs", afs_flock_mode_openafs },
{ Opt_flock, "strict", afs_flock_mode_strict },
{ Opt_flock, "write", afs_flock_mode_write },
static const struct fs_parameter_spec afs_fs_parameters[] = {
fsparam_flag ("autocell", Opt_autocell),
fsparam_flag ("dyn", Opt_dyn),
fsparam_enum ("flock", Opt_flock, afs_param_flock),
fsparam_string("source", Opt_source),
{}
};
static const struct fs_parameter_description afs_fs_parameters = {
.name = "kAFS",
.specs = afs_param_specs,
.enums = afs_param_enums,
};
/*
* initialise the filesystem
*/
......@@ -323,7 +317,7 @@ static int afs_parse_param(struct fs_context *fc, struct fs_parameter *param)
struct afs_fs_context *ctx = fc->fs_private;
int opt;
opt = fs_parse(fc, &afs_fs_parameters, param, &result);
opt = fs_parse(fc, afs_fs_parameters, param, &result);
if (opt < 0)
return opt;
......
......@@ -67,7 +67,7 @@ int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
if (uniq_len && memcmp(ent->uniquifier, fscache_uniq, uniq_len))
continue;
errorf(fc, "ceph: fscache cookie already registered for fsid %pU, use fsc=<uniquifier> option",
errorfc(fc, "fscache cookie already registered for fsid %pU, use fsc=<uniquifier> option",
fsid);
err = -EBUSY;
goto out_unlock;
......@@ -96,7 +96,7 @@ int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
list_add_tail(&ent->list, &ceph_fscache_list);
} else {
kfree(ent);
errorf(fc, "ceph: unable to register fscache cookie for fsid %pU",
errorfc(fc, "unable to register fscache cookie for fsid %pU",
fsid);
/* all other fs ignore this error */
}
......
......@@ -162,13 +162,13 @@ enum ceph_recover_session_mode {
ceph_recover_session_clean
};
static const struct fs_parameter_enum ceph_mount_param_enums[] = {
{ Opt_recover_session, "no", ceph_recover_session_no },
{ Opt_recover_session, "clean", ceph_recover_session_clean },
static const struct constant_table ceph_param_recover[] = {
{ "no", ceph_recover_session_no },
{ "clean", ceph_recover_session_clean },
{}
};
static const struct fs_parameter_spec ceph_mount_param_specs[] = {
static const struct fs_parameter_spec ceph_mount_parameters[] = {
fsparam_flag_no ("acl", Opt_acl),
fsparam_flag_no ("asyncreaddir", Opt_asyncreaddir),
fsparam_s32 ("caps_max", Opt_caps_max),
......@@ -178,8 +178,8 @@ static const struct fs_parameter_spec ceph_mount_param_specs[] = {
fsparam_flag_no ("copyfrom", Opt_copyfrom),
fsparam_flag_no ("dcache", Opt_dcache),
fsparam_flag_no ("dirstat", Opt_dirstat),
__fsparam (fs_param_is_string, "fsc", Opt_fscache,
fs_param_neg_with_no | fs_param_v_optional),
fsparam_flag_no ("fsc", Opt_fscache), // fsc|nofsc
fsparam_string ("fsc", Opt_fscache), // fsc=...
fsparam_flag_no ("ino32", Opt_ino32),
fsparam_string ("mds_namespace", Opt_mds_namespace),
fsparam_flag_no ("poolperm", Opt_poolperm),
......@@ -188,7 +188,7 @@ static const struct fs_parameter_spec ceph_mount_param_specs[] = {
fsparam_flag_no ("rbytes", Opt_rbytes),
fsparam_u32 ("readdir_max_bytes", Opt_readdir_max_bytes),
fsparam_u32 ("readdir_max_entries", Opt_readdir_max_entries),
fsparam_enum ("recover_session", Opt_recover_session),
fsparam_enum ("recover_session", Opt_recover_session, ceph_param_recover),
fsparam_flag_no ("require_active_mds", Opt_require_active_mds),
fsparam_u32 ("rsize", Opt_rsize),
fsparam_string ("snapdirname", Opt_snapdirname),
......@@ -197,12 +197,6 @@ static const struct fs_parameter_spec ceph_mount_param_specs[] = {
{}
};
static const struct fs_parameter_description ceph_mount_parameters = {
.name = "ceph",
.specs = ceph_mount_param_specs,
.enums = ceph_mount_param_enums,
};
struct ceph_parse_opts_ctx {
struct ceph_options *copts;
struct ceph_mount_options *opts;
......@@ -226,7 +220,7 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
dout("%s '%s'\n", __func__, dev_name);
if (!dev_name || !*dev_name)
return invalf(fc, "ceph: Empty source");
return invalfc(fc, "Empty source");
dev_name_end = strchr(dev_name, '/');
if (dev_name_end) {
......@@ -245,14 +239,14 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
dev_name_end--; /* back up to ':' separator */
if (dev_name_end < dev_name || *dev_name_end != ':')
return invalf(fc, "ceph: No path or : separator in source");
return invalfc(fc, "No path or : separator in source");
dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
if (fsopt->server_path)
dout("server path '%s'\n", fsopt->server_path);
ret = ceph_parse_mon_ips(param->string, dev_name_end - dev_name,
pctx->copts, fc);
pctx->copts, fc->log.log);
if (ret)
return ret;
......@@ -270,11 +264,11 @@ static int ceph_parse_mount_param(struct fs_context *fc,
unsigned int mode;
int token, ret;
ret = ceph_parse_param(param, pctx->copts, fc);
ret = ceph_parse_param(param, pctx->copts, fc->log.log);
if (ret != -ENOPARAM)
return ret;
token = fs_parse(fc, &ceph_mount_parameters, param, &result);
token = fs_parse(fc, ceph_mount_parameters, param, &result);
dout("%s fs_parse '%s' token %d\n", __func__, param->key, token);
if (token < 0)
return token;
......@@ -301,7 +295,7 @@ static int ceph_parse_mount_param(struct fs_context *fc,
break;
case Opt_source:
if (fc->source)
return invalf(fc, "ceph: Multiple sources specified");
return invalfc(fc, "Multiple sources specified");
return ceph_parse_source(param, fc);
case Opt_wsize:
if (result.uint_32 < PAGE_SIZE ||
......@@ -392,7 +386,7 @@ static int ceph_parse_mount_param(struct fs_context *fc,
}
break;
#else
return invalf(fc, "ceph: fscache support is disabled");
return invalfc(fc, "fscache support is disabled");
#endif
case Opt_poolperm:
if (!result.negated)
......@@ -423,7 +417,7 @@ static int ceph_parse_mount_param(struct fs_context *fc,
#ifdef CONFIG_CEPH_FS_POSIX_ACL
fc->sb_flags |= SB_POSIXACL;
#else
return invalf(fc, "ceph: POSIX ACL support is disabled");
return invalfc(fc, "POSIX ACL support is disabled");
#endif
} else {
fc->sb_flags &= ~SB_POSIXACL;
......@@ -435,7 +429,7 @@ static int ceph_parse_mount_param(struct fs_context *fc,
return 0;
out_of_range:
return invalf(fc, "ceph: %s out of range", param->key);
return invalfc(fc, "%s out of range", param->key);
}
static void destroy_mount_options(struct ceph_mount_options *args)
......@@ -1101,7 +1095,7 @@ static int ceph_get_tree(struct fs_context *fc)
dout("ceph_get_tree\n");
if (!fc->source)
return invalf(fc, "ceph: No source");
return invalfc(fc, "No source");
#ifdef CONFIG_CEPH_FS_POSIX_ACL
fc->sb_flags |= SB_POSIXACL;
......
......@@ -534,7 +534,7 @@ static int cramfs_read_super(struct super_block *sb, struct fs_context *fc,
/* check for wrong endianness */
if (super->magic == CRAMFS_MAGIC_WEND) {
if (!silent)
errorf(fc, "cramfs: wrong endianness");
errorfc(fc, "wrong endianness");
return -EINVAL;
}
......@@ -546,22 +546,22 @@ static int cramfs_read_super(struct super_block *sb, struct fs_context *fc,
mutex_unlock(&read_mutex);
if (super->magic != CRAMFS_MAGIC) {
if (super->magic == CRAMFS_MAGIC_WEND && !silent)
errorf(fc, "cramfs: wrong endianness");
errorfc(fc, "wrong endianness");
else if (!silent)
errorf(fc, "cramfs: wrong magic");
errorfc(fc, "wrong magic");
return -EINVAL;
}
}
/* get feature flags first */
if (super->flags & ~CRAMFS_SUPPORTED_FLAGS) {
errorf(fc, "cramfs: unsupported filesystem features");
errorfc(fc, "unsupported filesystem features");
return -EINVAL;
}
/* Check that the root inode is in a sane state */
if (!S_ISDIR(super->root.mode)) {
errorf(fc, "cramfs: root is not a directory");
errorfc(fc, "root is not a directory");
return -EINVAL;
}
/* correct strange, hard-coded permissions of mkcramfs */
......@@ -580,12 +580,12 @@ static int cramfs_read_super(struct super_block *sb, struct fs_context *fc,
sbi->magic = super->magic;
sbi->flags = super->flags;
if (root_offset == 0)
infof(fc, "cramfs: empty filesystem");
infofc(fc, "empty filesystem");
else if (!(super->flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
((root_offset != sizeof(struct cramfs_super)) &&
(root_offset != 512 + sizeof(struct cramfs_super))))
{
errorf(fc, "cramfs: bad root offset %lu", root_offset);
errorfc(fc, "bad root offset %lu", root_offset);
return -EINVAL;
}
......
......@@ -74,7 +74,8 @@ int register_filesystem(struct file_system_type * fs)
int res = 0;
struct file_system_type ** p;
if (fs->parameters && !fs_validate_description(fs->parameters))
if (fs->parameters &&
!fs_validate_description(fs->name, fs->parameters))
return -EINVAL;
BUG_ON(strchr(fs->name, '.'));
......
......@@ -45,6 +45,7 @@ static const struct constant_table common_set_sb_flag[] = {
{ "posixacl", SB_POSIXACL },
{ "ro", SB_RDONLY },
{ "sync", SB_SYNCHRONOUS },
{ },
};
static const struct constant_table common_clear_sb_flag[] = {
......@@ -53,6 +54,7 @@ static const struct constant_table common_clear_sb_flag[] = {
{ "nomand", SB_MANDLOCK },
{ "rw", SB_RDONLY },
{ "silent", SB_SILENT },
{ },
};
static const char *const forbidden_sb_flag[] = {
......@@ -175,14 +177,15 @@ int vfs_parse_fs_string(struct fs_context *fc, const char *key,
struct fs_parameter param = {
.key = key,
.type = fs_value_is_string,
.type = fs_value_is_flag,
.size = v_size,
};
if (v_size > 0) {
if (value) {
param.string = kmemdup_nul(value, v_size, GFP_KERNEL);
if (!param.string)
return -ENOMEM;
param.type = fs_value_is_string;
}
ret = vfs_parse_fs_param(fc, &param);
......@@ -268,6 +271,7 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
fc->fs_type = get_filesystem(fs_type);
fc->cred = get_current_cred();
fc->net_ns = get_net(current->nsproxy->net_ns);
fc->log.prefix = fs_type->name;
mutex_init(&fc->uapi_mutex);
......@@ -361,8 +365,8 @@ struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc)
get_net(fc->net_ns);
get_user_ns(fc->user_ns);
get_cred(fc->cred);