Blame SOURCES/0037-fs-ntfs3-Use-new-api-for-mounting.patch

Kmods SIG 8b815c
From 610f8f5a7baf998e70a61c63e53869b676d9b04c Mon Sep 17 00:00:00 2001
Kmods SIG 8b815c
From: Kari Argillander <kari.argillander@gmail.com>
Kmods SIG 8b815c
Date: Tue, 7 Sep 2021 18:35:52 +0300
Kmods SIG 8b815c
Subject: [Backport 610f8f5a7baf] src: Use new api for mounting
Kmods SIG 8b815c
Kmods SIG 8b815c
We have now new mount api as described in Documentation/filesystems. We
Kmods SIG 8b815c
should use it as it gives us some benefits which are desribed here
Kmods SIG 8b815c
lore.kernel.org/linux-fsdevel/159646178122.1784947.11705396571718464082.stgit@warthog.procyon.org.uk/
Kmods SIG 8b815c
Kmods SIG 8b815c
Nls loading is changed a to load with string. This did make code also
Kmods SIG 8b815c
little cleaner.
Kmods SIG 8b815c
Kmods SIG 8b815c
Also try to use fsparam_flag_no as much as possible. This is just nice
Kmods SIG 8b815c
little touch and is not mandatory but it should not make any harm. It
Kmods SIG 8b815c
is just convenient that we can use example acl/noacl mount options.
Kmods SIG 8b815c
Kmods SIG 8b815c
Signed-off-by: Kari Argillander <kari.argillander@gmail.com>
Kmods SIG 8b815c
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Kmods SIG 8b815c
---
Kmods SIG 8b815c
 src/ntfs_fs.h |   1 +
Kmods SIG 8b815c
 src/super.c   | 433 ++++++++++++++++++++++++---------------------
Kmods SIG 8b815c
 2 files changed, 229 insertions(+), 205 deletions(-)
Kmods SIG 8b815c
Kmods SIG 8b815c
diff --git a/src/ntfs_fs.h b/src/ntfs_fs.h
Kmods SIG 8b815c
index 98c90c399ee2f447f3ad5f0847c56ca7561f17fb..aa18f12b7096e2ecd7e6db365aaa0152d4fb2327 100644
Kmods SIG 8b815c
--- a/src/ntfs_fs.h
Kmods SIG 8b815c
+++ b/src/ntfs_fs.h
Kmods SIG 8b815c
@@ -52,6 +52,7 @@
Kmods SIG 8b815c
 // clang-format on
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 struct ntfs_mount_options {
Kmods SIG 8b815c
+	char *nls_name;
Kmods SIG 8b815c
 	struct nls_table *nls;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	kuid_t fs_uid;
Kmods SIG 8b815c
diff --git a/src/super.c b/src/super.c
Kmods SIG 8b815c
index 0f38203420515b6386bdd51e83c402c431743946..befa78d3cb26767e401c84cc87a40006c4603186 100644
Kmods SIG 8b815c
--- a/src/super.c
Kmods SIG 8b815c
+++ b/src/super.c
Kmods SIG 8b815c
@@ -28,11 +28,12 @@
Kmods SIG 8b815c
 #include <linux/buffer_head.h>
Kmods SIG 8b815c
 #include <linux/exportfs.h>
Kmods SIG 8b815c
 #include <linux/fs.h>
Kmods SIG 8b815c
+#include <linux/fs_context.h>
Kmods SIG 8b815c
+#include <linux/fs_parser.h>
Kmods SIG 8b815c
 #include <linux/iversion.h>
Kmods SIG 8b815c
 #include <linux/log2.h>
Kmods SIG 8b815c
 #include <linux/module.h>
Kmods SIG 8b815c
 #include <linux/nls.h>
Kmods SIG 8b815c
-#include <linux/parser.h>
Kmods SIG 8b815c
 #include <linux/seq_file.h>
Kmods SIG 8b815c
 #include <linux/statfs.h>
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -205,9 +206,11 @@ void *ntfs_put_shared(void *ptr)
Kmods SIG 8b815c
 	return ret;
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-static inline void clear_mount_options(struct ntfs_mount_options *options)
Kmods SIG 8b815c
+static inline void put_mount_options(struct ntfs_mount_options *options)
Kmods SIG 8b815c
 {
Kmods SIG 8b815c
+	kfree(options->nls_name);
Kmods SIG 8b815c
 	unload_nls(options->nls);
Kmods SIG 8b815c
+	kfree(options);
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 enum Opt {
Kmods SIG 8b815c
@@ -229,205 +232,171 @@ enum Opt {
Kmods SIG 8b815c
 	Opt_err,
Kmods SIG 8b815c
 };
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-static const match_table_t ntfs_tokens = {
Kmods SIG 8b815c
-	{ Opt_uid, "uid=%u" },
Kmods SIG 8b815c
-	{ Opt_gid, "gid=%u" },
Kmods SIG 8b815c
-	{ Opt_umask, "umask=%o" },
Kmods SIG 8b815c
-	{ Opt_dmask, "dmask=%o" },
Kmods SIG 8b815c
-	{ Opt_fmask, "fmask=%o" },
Kmods SIG 8b815c
-	{ Opt_immutable, "sys_immutable" },
Kmods SIG 8b815c
-	{ Opt_discard, "discard" },
Kmods SIG 8b815c
-	{ Opt_force, "force" },
Kmods SIG 8b815c
-	{ Opt_sparse, "sparse" },
Kmods SIG 8b815c
-	{ Opt_nohidden, "nohidden" },
Kmods SIG 8b815c
-	{ Opt_acl, "acl" },
Kmods SIG 8b815c
-	{ Opt_showmeta, "showmeta" },
Kmods SIG 8b815c
-	{ Opt_nls, "nls=%s" },
Kmods SIG 8b815c
-	{ Opt_prealloc, "prealloc" },
Kmods SIG 8b815c
-	{ Opt_no_acs_rules, "no_acs_rules" },
Kmods SIG 8b815c
-	{ Opt_err, NULL },
Kmods SIG 8b815c
+static const struct fs_parameter_spec ntfs_fs_parameters[] = {
Kmods SIG 8b815c
+	fsparam_u32("uid",			Opt_uid),
Kmods SIG 8b815c
+	fsparam_u32("gid",			Opt_gid),
Kmods SIG 8b815c
+	fsparam_u32oct("umask",			Opt_umask),
Kmods SIG 8b815c
+	fsparam_u32oct("dmask",			Opt_dmask),
Kmods SIG 8b815c
+	fsparam_u32oct("fmask",			Opt_fmask),
Kmods SIG 8b815c
+	fsparam_flag_no("sys_immutable",	Opt_immutable),
Kmods SIG 8b815c
+	fsparam_flag_no("discard",		Opt_discard),
Kmods SIG 8b815c
+	fsparam_flag_no("force",		Opt_force),
Kmods SIG 8b815c
+	fsparam_flag_no("sparse",		Opt_sparse),
Kmods SIG 8b815c
+	fsparam_flag("nohidden",		Opt_nohidden),
Kmods SIG 8b815c
+	fsparam_flag_no("acl",			Opt_acl),
Kmods SIG 8b815c
+	fsparam_flag_no("showmeta",		Opt_showmeta),
Kmods SIG 8b815c
+	fsparam_string("nls",			Opt_nls),
Kmods SIG 8b815c
+	fsparam_flag_no("prealloc",		Opt_prealloc),
Kmods SIG 8b815c
+	fsparam_flag("no_acs_rules",		Opt_no_acs_rules),
Kmods SIG 8b815c
+	{}
Kmods SIG 8b815c
 };
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-static noinline int ntfs_parse_options(struct super_block *sb, char *options,
Kmods SIG 8b815c
-				       int silent,
Kmods SIG 8b815c
-				       struct ntfs_mount_options *opts)
Kmods SIG 8b815c
+/*
Kmods SIG 8b815c
+ * Load nls table or if @nls is utf8 then return NULL.
Kmods SIG 8b815c
+ */
Kmods SIG 8b815c
+static struct nls_table *ntfs_load_nls(char *nls)
Kmods SIG 8b815c
 {
Kmods SIG 8b815c
-	char *p;
Kmods SIG 8b815c
-	substring_t args[MAX_OPT_ARGS];
Kmods SIG 8b815c
-	int option;
Kmods SIG 8b815c
-	char nls_name[30];
Kmods SIG 8b815c
-	struct nls_table *nls;
Kmods SIG 8b815c
+	struct nls_table *ret;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	opts->fs_uid = current_uid();
Kmods SIG 8b815c
-	opts->fs_gid = current_gid();
Kmods SIG 8b815c
-	opts->fs_fmask_inv = opts->fs_dmask_inv = ~current_umask();
Kmods SIG 8b815c
-	nls_name[0] = 0;
Kmods SIG 8b815c
+	if (!nls)
Kmods SIG 8b815c
+		nls = CONFIG_NLS_DEFAULT;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	if (!options)
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+	if (strcmp(nls, "utf8") == 0)
Kmods SIG 8b815c
+		return NULL;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	while ((p = strsep(&options, ","))) {
Kmods SIG 8b815c
-		int token;
Kmods SIG 8b815c
+	if (strcmp(nls, CONFIG_NLS_DEFAULT) == 0)
Kmods SIG 8b815c
+		return load_nls_default();
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-		if (!*p)
Kmods SIG 8b815c
-			continue;
Kmods SIG 8b815c
+	ret = load_nls(nls);
Kmods SIG 8b815c
+	if (ret)
Kmods SIG 8b815c
+		return ret;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-		token = match_token(p, ntfs_tokens, args);
Kmods SIG 8b815c
-		switch (token) {
Kmods SIG 8b815c
-		case Opt_immutable:
Kmods SIG 8b815c
-			opts->sys_immutable = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_uid:
Kmods SIG 8b815c
-			if (match_int(&args[0], &option))
Kmods SIG 8b815c
-				return -EINVAL;
Kmods SIG 8b815c
-			opts->fs_uid = make_kuid(current_user_ns(), option);
Kmods SIG 8b815c
-			if (!uid_valid(opts->fs_uid))
Kmods SIG 8b815c
-				return -EINVAL;
Kmods SIG 8b815c
-			opts->uid = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_gid:
Kmods SIG 8b815c
-			if (match_int(&args[0], &option))
Kmods SIG 8b815c
-				return -EINVAL;
Kmods SIG 8b815c
-			opts->fs_gid = make_kgid(current_user_ns(), option);
Kmods SIG 8b815c
-			if (!gid_valid(opts->fs_gid))
Kmods SIG 8b815c
-				return -EINVAL;
Kmods SIG 8b815c
-			opts->gid = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_umask:
Kmods SIG 8b815c
-			if (match_octal(&args[0], &option))
Kmods SIG 8b815c
-				return -EINVAL;
Kmods SIG 8b815c
-			opts->fs_fmask_inv = opts->fs_dmask_inv = ~option;
Kmods SIG 8b815c
-			opts->fmask = opts->dmask = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_dmask:
Kmods SIG 8b815c
-			if (match_octal(&args[0], &option))
Kmods SIG 8b815c
-				return -EINVAL;
Kmods SIG 8b815c
-			opts->fs_dmask_inv = ~option;
Kmods SIG 8b815c
-			opts->dmask = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_fmask:
Kmods SIG 8b815c
-			if (match_octal(&args[0], &option))
Kmods SIG 8b815c
-				return -EINVAL;
Kmods SIG 8b815c
-			opts->fs_fmask_inv = ~option;
Kmods SIG 8b815c
-			opts->fmask = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_discard:
Kmods SIG 8b815c
-			opts->discard = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_force:
Kmods SIG 8b815c
-			opts->force = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_sparse:
Kmods SIG 8b815c
-			opts->sparse = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_nohidden:
Kmods SIG 8b815c
-			opts->nohidden = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_acl:
Kmods SIG 8b815c
+	return ERR_PTR(-EINVAL);
Kmods SIG 8b815c
+}
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+static int ntfs_fs_parse_param(struct fs_context *fc,
Kmods SIG 8b815c
+			       struct fs_parameter *param)
Kmods SIG 8b815c
+{
Kmods SIG 8b815c
+	struct ntfs_mount_options *opts = fc->fs_private;
Kmods SIG 8b815c
+	struct fs_parse_result result;
Kmods SIG 8b815c
+	int opt;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	opt = fs_parse(fc, ntfs_fs_parameters, param, &result);
Kmods SIG 8b815c
+	if (opt < 0)
Kmods SIG 8b815c
+		return opt;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	switch (opt) {
Kmods SIG 8b815c
+	case Opt_uid:
Kmods SIG 8b815c
+		opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
Kmods SIG 8b815c
+		if (!uid_valid(opts->fs_uid))
Kmods SIG 8b815c
+			return invalf(fc, "ntfs3: Invalid value for uid.");
Kmods SIG 8b815c
+		opts->uid = 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_gid:
Kmods SIG 8b815c
+		opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
Kmods SIG 8b815c
+		if (!gid_valid(opts->fs_gid))
Kmods SIG 8b815c
+			return invalf(fc, "ntfs3: Invalid value for gid.");
Kmods SIG 8b815c
+		opts->gid = 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_umask:
Kmods SIG 8b815c
+		if (result.uint_32 & ~07777)
Kmods SIG 8b815c
+			return invalf(fc, "ntfs3: Invalid value for umask.");
Kmods SIG 8b815c
+		opts->fs_fmask_inv = ~result.uint_32;
Kmods SIG 8b815c
+		opts->fs_dmask_inv = ~result.uint_32;
Kmods SIG 8b815c
+		opts->fmask = 1;
Kmods SIG 8b815c
+		opts->dmask = 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_dmask:
Kmods SIG 8b815c
+		if (result.uint_32 & ~07777)
Kmods SIG 8b815c
+			return invalf(fc, "ntfs3: Invalid value for dmask.");
Kmods SIG 8b815c
+		opts->fs_dmask_inv = ~result.uint_32;
Kmods SIG 8b815c
+		opts->dmask = 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_fmask:
Kmods SIG 8b815c
+		if (result.uint_32 & ~07777)
Kmods SIG 8b815c
+			return invalf(fc, "ntfs3: Invalid value for fmask.");
Kmods SIG 8b815c
+		opts->fs_fmask_inv = ~result.uint_32;
Kmods SIG 8b815c
+		opts->fmask = 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_immutable:
Kmods SIG 8b815c
+		opts->sys_immutable = result.negated ? 0 : 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_discard:
Kmods SIG 8b815c
+		opts->discard = result.negated ? 0 : 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_force:
Kmods SIG 8b815c
+		opts->force = result.negated ? 0 : 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_sparse:
Kmods SIG 8b815c
+		opts->sparse = result.negated ? 0 : 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_nohidden:
Kmods SIG 8b815c
+		opts->nohidden = 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_acl:
Kmods SIG 8b815c
+		if (!result.negated)
Kmods SIG 8b815c
 #ifdef CONFIG_NTFS3_FS_POSIX_ACL
Kmods SIG 8b815c
-			sb->s_flags |= SB_POSIXACL;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
+			fc->sb_flags |= SB_POSIXACL;
Kmods SIG 8b815c
 #else
Kmods SIG 8b815c
-			ntfs_err(sb, "support for ACL not compiled in!");
Kmods SIG 8b815c
-			return -EINVAL;
Kmods SIG 8b815c
+			return invalf(fc, "ntfs3: Support for ACL not compiled in!");
Kmods SIG 8b815c
 #endif
Kmods SIG 8b815c
-		case Opt_showmeta:
Kmods SIG 8b815c
-			opts->showmeta = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_nls:
Kmods SIG 8b815c
-			match_strlcpy(nls_name, &args[0], sizeof(nls_name));
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_prealloc:
Kmods SIG 8b815c
-			opts->prealloc = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		case Opt_no_acs_rules:
Kmods SIG 8b815c
-			opts->no_acs_rules = 1;
Kmods SIG 8b815c
-			break;
Kmods SIG 8b815c
-		default:
Kmods SIG 8b815c
-			if (!silent)
Kmods SIG 8b815c
-				ntfs_err(
Kmods SIG 8b815c
-					sb,
Kmods SIG 8b815c
-					"Unrecognized mount option \"%s\" or missing value",
Kmods SIG 8b815c
-					p);
Kmods SIG 8b815c
-			//return -EINVAL;
Kmods SIG 8b815c
-		}
Kmods SIG 8b815c
-	}
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-out:
Kmods SIG 8b815c
-	if (!strcmp(nls_name[0] ? nls_name : CONFIG_NLS_DEFAULT, "utf8")) {
Kmods SIG 8b815c
-		/*
Kmods SIG 8b815c
-		 * For UTF-8 use utf16s_to_utf8s()/utf8s_to_utf16s()
Kmods SIG 8b815c
-		 * instead of NLS.
Kmods SIG 8b815c
-		 */
Kmods SIG 8b815c
-		nls = NULL;
Kmods SIG 8b815c
-	} else if (nls_name[0]) {
Kmods SIG 8b815c
-		nls = load_nls(nls_name);
Kmods SIG 8b815c
-		if (!nls) {
Kmods SIG 8b815c
-			ntfs_err(sb, "failed to load \"%s\"", nls_name);
Kmods SIG 8b815c
-			return -EINVAL;
Kmods SIG 8b815c
-		}
Kmods SIG 8b815c
-	} else {
Kmods SIG 8b815c
-		nls = load_nls_default();
Kmods SIG 8b815c
-		if (!nls) {
Kmods SIG 8b815c
-			ntfs_err(sb, "failed to load default nls");
Kmods SIG 8b815c
-			return -EINVAL;
Kmods SIG 8b815c
-		}
Kmods SIG 8b815c
+		else
Kmods SIG 8b815c
+			fc->sb_flags &= ~SB_POSIXACL;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_showmeta:
Kmods SIG 8b815c
+		opts->showmeta = result.negated ? 0 : 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_nls:
Kmods SIG 8b815c
+		kfree(opts->nls_name);
Kmods SIG 8b815c
+		opts->nls_name = param->string;
Kmods SIG 8b815c
+		param->string = NULL;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_prealloc:
Kmods SIG 8b815c
+		opts->prealloc = result.negated ? 0 : 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	case Opt_no_acs_rules:
Kmods SIG 8b815c
+		opts->no_acs_rules = 1;
Kmods SIG 8b815c
+		break;
Kmods SIG 8b815c
+	default:
Kmods SIG 8b815c
+		/* Should not be here unless we forget add case. */
Kmods SIG 8b815c
+		return -EINVAL;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
-	opts->nls = nls;
Kmods SIG 8b815c
-
Kmods SIG 8b815c
 	return 0;
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-static int ntfs_remount(struct super_block *sb, int *flags, char *data)
Kmods SIG 8b815c
+static int ntfs_fs_reconfigure(struct fs_context *fc)
Kmods SIG 8b815c
 {
Kmods SIG 8b815c
-	int err, ro_rw;
Kmods SIG 8b815c
+	struct super_block *sb = fc->root->d_sb;
Kmods SIG 8b815c
 	struct ntfs_sb_info *sbi = sb->s_fs_info;
Kmods SIG 8b815c
-	struct ntfs_mount_options old_opts;
Kmods SIG 8b815c
-	char *orig_data = kstrdup(data, GFP_KERNEL);
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	if (data && !orig_data)
Kmods SIG 8b815c
-		return -ENOMEM;
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	/* Store  original options. */
Kmods SIG 8b815c
-	memcpy(&old_opts, sbi->options, sizeof(old_opts));
Kmods SIG 8b815c
-	clear_mount_options(sbi->options);
Kmods SIG 8b815c
-	memset(sbi->options, 0, sizeof(old_opts));
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	err = ntfs_parse_options(sb, data, 0, sbi->options);
Kmods SIG 8b815c
-	if (err)
Kmods SIG 8b815c
-		goto restore_opts;
Kmods SIG 8b815c
+	struct ntfs_mount_options *new_opts = fc->fs_private;
Kmods SIG 8b815c
+	int ro_rw;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	ro_rw = sb_rdonly(sb) && !(*flags & SB_RDONLY);
Kmods SIG 8b815c
+	ro_rw = sb_rdonly(sb) && !(fc->sb_flags & SB_RDONLY);
Kmods SIG 8b815c
 	if (ro_rw && (sbi->flags & NTFS_FLAGS_NEED_REPLAY)) {
Kmods SIG 8b815c
-		ntfs_warn(
Kmods SIG 8b815c
-			sb,
Kmods SIG 8b815c
-			"Couldn't remount rw because journal is not replayed. Please umount/remount instead\n");
Kmods SIG 8b815c
-		err = -EINVAL;
Kmods SIG 8b815c
-		goto restore_opts;
Kmods SIG 8b815c
+		errorf(fc, "ntfs3: Couldn't remount rw because journal is not replayed. Please umount/remount instead\n");
Kmods SIG 8b815c
+		return -EINVAL;
Kmods SIG 8b815c
+	}
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	new_opts->nls = ntfs_load_nls(new_opts->nls_name);
Kmods SIG 8b815c
+	if (IS_ERR(new_opts->nls)) {
Kmods SIG 8b815c
+		new_opts->nls = NULL;
Kmods SIG 8b815c
+		errorf(fc, "ntfs3: Cannot load nls %s", new_opts->nls_name);
Kmods SIG 8b815c
+		return -EINVAL;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
+	if (new_opts->nls != sbi->options->nls)
Kmods SIG 8b815c
+		return invalf(fc, "ntfs3: Cannot use different nls when remounting!");
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	sync_filesystem(sb);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	if (ro_rw && (sbi->volume.flags & VOLUME_FLAG_DIRTY) &&
Kmods SIG 8b815c
-	    !sbi->options->force) {
Kmods SIG 8b815c
-		ntfs_warn(sb, "volume is dirty and \"force\" flag is not set!");
Kmods SIG 8b815c
-		err = -EINVAL;
Kmods SIG 8b815c
-		goto restore_opts;
Kmods SIG 8b815c
+	    !new_opts->force) {
Kmods SIG 8b815c
+		errorf(fc, "ntfs3: Volume is dirty and \"force\" flag is not set!");
Kmods SIG 8b815c
+		return -EINVAL;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	clear_mount_options(&old_opts);
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	ntfs_info(sb, "re-mounted. Opts: %s", orig_data);
Kmods SIG 8b815c
-	err = 0;
Kmods SIG 8b815c
-	goto out;
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-restore_opts:
Kmods SIG 8b815c
-	clear_mount_options(sbi->options);
Kmods SIG 8b815c
-	memcpy(sbi->options, &old_opts, sizeof(old_opts));
Kmods SIG 8b815c
+	memcpy(sbi->options, new_opts, sizeof(*new_opts));
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-out:
Kmods SIG 8b815c
-	kfree(orig_data);
Kmods SIG 8b815c
-	return err;
Kmods SIG 8b815c
+	return 0;
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 static struct kmem_cache *ntfs_inode_cachep;
Kmods SIG 8b815c
@@ -506,9 +475,6 @@ static noinline void put_ntfs(struct ntfs_sb_info *sbi)
Kmods SIG 8b815c
 	xpress_free_decompressor(sbi->compress.xpress);
Kmods SIG 8b815c
 	lzx_free_decompressor(sbi->compress.lzx);
Kmods SIG 8b815c
 #endif
Kmods SIG 8b815c
-	clear_mount_options(sbi->options);
Kmods SIG 8b815c
-	kfree(sbi->options);
Kmods SIG 8b815c
-
Kmods SIG 8b815c
 	kfree(sbi);
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -519,7 +485,9 @@ static void ntfs_put_super(struct super_block *sb)
Kmods SIG 8b815c
 	/* Mark rw ntfs as clear, if possible. */
Kmods SIG 8b815c
 	ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
+	put_mount_options(sbi->options);
Kmods SIG 8b815c
 	put_ntfs(sbi);
Kmods SIG 8b815c
+	sb->s_fs_info = NULL;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	sync_blockdev(sb->s_bdev);
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
@@ -635,7 +603,6 @@ static const struct super_operations ntfs_sops = {
Kmods SIG 8b815c
 	.statfs = ntfs_statfs,
Kmods SIG 8b815c
 	.show_options = ntfs_show_options,
Kmods SIG 8b815c
 	.sync_fs = ntfs_sync_fs,
Kmods SIG 8b815c
-	.remount_fs = ntfs_remount,
Kmods SIG 8b815c
 	.write_inode = ntfs3_write_inode,
Kmods SIG 8b815c
 };
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -905,10 +872,10 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
Kmods SIG 8b815c
 /*
Kmods SIG 8b815c
  * ntfs_fill_super - Try to mount.
Kmods SIG 8b815c
  */
Kmods SIG 8b815c
-static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
Kmods SIG 8b815c
+static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 {
Kmods SIG 8b815c
 	int err;
Kmods SIG 8b815c
-	struct ntfs_sb_info *sbi;
Kmods SIG 8b815c
+	struct ntfs_sb_info *sbi = sb->s_fs_info;
Kmods SIG 8b815c
 	struct block_device *bdev = sb->s_bdev;
Kmods SIG 8b815c
 	struct inode *bd_inode = bdev->bd_inode;
Kmods SIG 8b815c
 	struct request_queue *rq = bdev_get_queue(bdev);
Kmods SIG 8b815c
@@ -927,17 +894,6 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	ref.high = 0;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	sbi = kzalloc(sizeof(struct ntfs_sb_info), GFP_NOFS);
Kmods SIG 8b815c
-	if (!sbi)
Kmods SIG 8b815c
-		return -ENOMEM;
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	sbi->options = kzalloc(sizeof(struct ntfs_mount_options), GFP_NOFS);
Kmods SIG 8b815c
-	if (!sbi->options) {
Kmods SIG 8b815c
-		kfree(sbi);
Kmods SIG 8b815c
-		return -ENOMEM;
Kmods SIG 8b815c
-	}
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	sb->s_fs_info = sbi;
Kmods SIG 8b815c
 	sbi->sb = sb;
Kmods SIG 8b815c
 	sb->s_flags |= SB_NODIRATIME;
Kmods SIG 8b815c
 	sb->s_magic = 0x7366746e; // "ntfs"
Kmods SIG 8b815c
@@ -949,9 +905,12 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
Kmods SIG 8b815c
 	ratelimit_state_init(&sbi->msg_ratelimit, DEFAULT_RATELIMIT_INTERVAL,
Kmods SIG 8b815c
 			     DEFAULT_RATELIMIT_BURST);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	err = ntfs_parse_options(sb, data, silent, sbi->options);
Kmods SIG 8b815c
-	if (err)
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+	sbi->options->nls = ntfs_load_nls(sbi->options->nls_name);
Kmods SIG 8b815c
+	if (IS_ERR(sbi->options->nls)) {
Kmods SIG 8b815c
+		sbi->options->nls = NULL;
Kmods SIG 8b815c
+		errorf(fc, "Cannot load nls %s", sbi->options->nls_name);
Kmods SIG 8b815c
+		return -EINVAL;
Kmods SIG 8b815c
+	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	if (!rq || !blk_queue_discard(rq) || !rq->limits.discard_granularity) {
Kmods SIG 8b815c
 		;
Kmods SIG 8b815c
@@ -1344,6 +1303,9 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
Kmods SIG 8b815c
 		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
+	fc->fs_private = NULL;
Kmods SIG 8b815c
+	fc->s_fs_info = NULL;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
 	return 0;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 out:
Kmods SIG 8b815c
@@ -1354,9 +1316,6 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
Kmods SIG 8b815c
 		sb->s_root = NULL;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	put_ntfs(sbi);
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	sb->s_fs_info = NULL;
Kmods SIG 8b815c
 	return err;
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -1426,19 +1385,83 @@ int ntfs_discard(struct ntfs_sb_info *sbi, CLST lcn, CLST len)
Kmods SIG 8b815c
 	return err;
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-static struct dentry *ntfs_mount(struct file_system_type *fs_type, int flags,
Kmods SIG 8b815c
-				 const char *dev_name, void *data)
Kmods SIG 8b815c
+static int ntfs_fs_get_tree(struct fs_context *fc)
Kmods SIG 8b815c
+{
Kmods SIG 8b815c
+	return get_tree_bdev(fc, ntfs_fill_super);
Kmods SIG 8b815c
+}
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+/*
Kmods SIG 8b815c
+ * ntfs_fs_free - Free fs_context.
Kmods SIG 8b815c
+ *
Kmods SIG 8b815c
+ * Note that this will be called after fill_super and reconfigure
Kmods SIG 8b815c
+ * even when they pass. So they have to take pointers if they pass.
Kmods SIG 8b815c
+ */
Kmods SIG 8b815c
+static void ntfs_fs_free(struct fs_context *fc)
Kmods SIG 8b815c
+{
Kmods SIG 8b815c
+	struct ntfs_mount_options *opts = fc->fs_private;
Kmods SIG 8b815c
+	struct ntfs_sb_info *sbi = fc->s_fs_info;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	if (sbi)
Kmods SIG 8b815c
+		put_ntfs(sbi);
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	if (opts)
Kmods SIG 8b815c
+		put_mount_options(opts);
Kmods SIG 8b815c
+}
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+static const struct fs_context_operations ntfs_context_ops = {
Kmods SIG 8b815c
+	.parse_param	= ntfs_fs_parse_param,
Kmods SIG 8b815c
+	.get_tree	= ntfs_fs_get_tree,
Kmods SIG 8b815c
+	.reconfigure	= ntfs_fs_reconfigure,
Kmods SIG 8b815c
+	.free		= ntfs_fs_free,
Kmods SIG 8b815c
+};
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+/*
Kmods SIG 8b815c
+ * ntfs_init_fs_context - Initialize spi and opts
Kmods SIG 8b815c
+ *
Kmods SIG 8b815c
+ * This will called when mount/remount. We will first initiliaze
Kmods SIG 8b815c
+ * options so that if remount we can use just that.
Kmods SIG 8b815c
+ */
Kmods SIG 8b815c
+static int ntfs_init_fs_context(struct fs_context *fc)
Kmods SIG 8b815c
 {
Kmods SIG 8b815c
-	return mount_bdev(fs_type, flags, dev_name, data, ntfs_fill_super);
Kmods SIG 8b815c
+	struct ntfs_mount_options *opts;
Kmods SIG 8b815c
+	struct ntfs_sb_info *sbi;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	opts = kzalloc(sizeof(struct ntfs_mount_options), GFP_NOFS);
Kmods SIG 8b815c
+	if (!opts)
Kmods SIG 8b815c
+		return -ENOMEM;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	/* Default options. */
Kmods SIG 8b815c
+	opts->fs_uid = current_uid();
Kmods SIG 8b815c
+	opts->fs_gid = current_gid();
Kmods SIG 8b815c
+	opts->fs_fmask_inv = ~current_umask();
Kmods SIG 8b815c
+	opts->fs_dmask_inv = ~current_umask();
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
Kmods SIG 8b815c
+		goto ok;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	sbi = kzalloc(sizeof(struct ntfs_sb_info), GFP_NOFS);
Kmods SIG 8b815c
+	if (!sbi) {
Kmods SIG 8b815c
+		kfree(opts);
Kmods SIG 8b815c
+		return -ENOMEM;
Kmods SIG 8b815c
+	}
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	sbi->options = opts;
Kmods SIG 8b815c
+	fc->s_fs_info = sbi;
Kmods SIG 8b815c
+ok:
Kmods SIG 8b815c
+	fc->fs_private = opts;
Kmods SIG 8b815c
+	fc->ops = &ntfs_context_ops;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+	return 0;
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 // clang-format off
Kmods SIG 8b815c
 static struct file_system_type ntfs_fs_type = {
Kmods SIG 8b815c
-	.owner		= THIS_MODULE,
Kmods SIG 8b815c
-	.name		= "ntfs3",
Kmods SIG 8b815c
-	.mount		= ntfs_mount,
Kmods SIG 8b815c
-	.kill_sb	= kill_block_super,
Kmods SIG 8b815c
-	.fs_flags	= FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
Kmods SIG 8b815c
+	.owner			= THIS_MODULE,
Kmods SIG 8b815c
+	.name			= "ntfs3",
Kmods SIG 8b815c
+	.init_fs_context	= ntfs_init_fs_context,
Kmods SIG 8b815c
+	.parameters		= ntfs_fs_parameters,
Kmods SIG 8b815c
+	.kill_sb		= kill_block_super,
Kmods SIG 8b815c
+	.fs_flags		= FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
Kmods SIG 8b815c
 };
Kmods SIG 8b815c
 // clang-format on
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-- 
Kmods SIG 8b815c
2.31.1
Kmods SIG 8b815c