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

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