@@ -866,7 +866,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
if (!skip_parsing) {
opt = fs_parse(fc, smb3_fs_parameters, param, &result);
if (opt < 0)
- return ctx->sloppy ? 1 : opt;
+ return opt;
}
switch (opt) {
@@ -187,6 +187,28 @@ int vfs_parse_fs_string(struct fs_context *fc, const char *key,
}
EXPORT_SYMBOL(vfs_parse_fs_string);
+
+static bool check_for_sloppy_option(void *options)
+{
+ char *sloppy;
+ char last;
+
+ sloppy = strstr(options, "sloppy");
+ if (!sloppy)
+ return false;
+
+ last = sloppy[6];
+
+ if (sloppy == options) {
+ if (last == 0 || last == ',')
+ return true;
+ } else if (*(--sloppy) == ',') {
+ if (last == 0 || last == ',')
+ return true;
+ }
+ return false;
+}
+
/**
* generic_parse_monolithic - Parse key[=val][,key[=val]]* mount data
* @ctx: The superblock configuration to fill in.
@@ -201,6 +223,7 @@ EXPORT_SYMBOL(vfs_parse_fs_string);
int generic_parse_monolithic(struct fs_context *fc, void *data)
{
char *options = data, *key;
+ bool sloppy = false;
int ret = 0;
if (!options)
@@ -210,11 +233,17 @@ int generic_parse_monolithic(struct fs_context *fc, void *data)
if (ret)
return ret;
+ if (fc->fs_type->fs_flags & FS_ALLOW_LEGACY_SLOPPY)
+ sloppy = check_for_sloppy_option(options);
+
while ((key = strsep(&options, ",")) != NULL) {
if (*key) {
size_t v_len = 0;
char *value = strchr(key, '=');
+ if (sloppy && !strcmp(key, "sloppy"))
+ continue;
+
if (value) {
if (value == key)
continue;
@@ -222,7 +251,7 @@ int generic_parse_monolithic(struct fs_context *fc, void *data)
v_len = strlen(value);
}
ret = vfs_parse_fs_string(fc, key, value, v_len);
- if (ret < 0)
+ if (!sloppy && ret < 0)
break;
}
}
@@ -485,7 +485,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
opt = fs_parse(fc, nfs_fs_parameters, param, &result);
if (opt < 0)
- return (opt == -ENOPARAM && ctx->sloppy) ? 1 : opt;
+ return opt;
if (fc->security)
ctx->has_sec_mnt_opts = 1;
@@ -2533,6 +2533,7 @@ struct file_system_type {
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
#define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */
#define FS_ALLOW_IDMAP 32 /* FS has been updated to handle vfs idmappings. */
+#define FS_ALLOW_LEGACY_SLOPPY 64 /* FS allows "sloppy" option handling behaviour */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
int (*init_fs_context)(struct fs_context *);
const struct fs_parameter_spec *parameters;
The sloppy option doesn't make sense for fsconfig() and knowedge of how to handle this case needs to be present in the caller. It does make sense in the legacy options parser, generic_parse_monolithic(), so it should allow for it. The sloppy option needs to be independent of the order in which it's given. The simplest way to do this in generic_parse_monolithic() is to check for it's presence, check if the file system supports it, then skip occurrances of it when walking the options string. Signed-off-by: Ian Kent <raven@themaw.net> --- fs/cifs/fs_context.c | 2 +- fs/fs_context.c | 31 ++++++++++++++++++++++++++++++- fs/nfs/fs_context.c | 2 +- include/linux/fs.h | 1 + 4 files changed, 33 insertions(+), 3 deletions(-)