diff mbox series

[RFC] vfs: handle sloppy option in fs context monolithic parser

Message ID 167963635629.253682.12145104262169969353.stgit@donald.themaw.net (mailing list archive)
State Mainlined, archived
Headers show
Series [RFC] vfs: handle sloppy option in fs context monolithic parser | expand

Commit Message

Ian Kent March 24, 2023, 5:39 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
index 6d13f8207e96..d7e9356797ab 100644
--- a/fs/cifs/fs_context.c
+++ b/fs/cifs/fs_context.c
@@ -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) {
diff --git a/fs/fs_context.c b/fs/fs_context.c
index 24ce12f0db32..fa179e1b8061 100644
--- a/fs/fs_context.c
+++ b/fs/fs_context.c
@@ -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;
 		}
 	}
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index 9bcd53d5c7d4..e8818b68ce3f 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -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;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c1769a2c5d70..ca05111767cb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -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;