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

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