linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API
@ 2024-03-05 23:07 Eric Sandeen
  2024-03-05 23:08 ` [PATCH 1/2] vfs: Convert debugfs to use " Eric Sandeen
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Eric Sandeen @ 2024-03-05 23:07 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Steven Rostedt, Greg Kroah-Hartman, Rafael J. Wysocki,
	Christian Brauner, Bill O'Donnell, David Howells

Since debugfs and tracefs are cut & pasted one way or the other,
do these at the same time.

Both of these patches originated in dhowells' tree at
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=mount-api-viro

https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=mount-api-viro&id=ec14be9e2aa76f63458466bba86256e123ec4e51
and
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=mount-api-viro&id=c4f2e60465859e02a6e36ed618dbaea16de8c8e0

I've forward-ported them to the mount API that landed, and
fixed up remounting; ->reconfigure() needed to copy the
parsed context options into the current superblock options
to effect any remount changes.

While these do use the invalf() functions for some errors, they
are new messages, not messages that used to go to dmesg that
would be lost if userspace isn't listening.

I've done minimal testing - booting with the patches, testing
some of the remount behavior for mode & uid.
Oh, and I built it too. </brown_paper_bag>

thanks,
-Eric


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-05 23:07 [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API Eric Sandeen
@ 2024-03-05 23:08 ` Eric Sandeen
  2024-03-06 10:50   ` Christian Brauner
  2024-03-07 21:10   ` Greg Kroah-Hartman
  2024-03-05 23:09 ` [PATCH 2/2] vfs: Convert tracefs " Eric Sandeen
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 13+ messages in thread
From: Eric Sandeen @ 2024-03-05 23:08 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Steven Rostedt, Greg Kroah-Hartman, Rafael J. Wysocki,
	Christian Brauner, Bill O'Donnell, David Howells

From: David Howells <dhowells@redhat.com>

Convert the debugfs filesystem to the new internal mount API as the old
one will be obsoleted and removed.  This allows greater flexibility in
communication of mount parameters between userspace, the VFS and the
filesystem.

See Documentation/filesystems/mount_api.txt for more information.

Signed-off-by: David Howells <dhowells@redhat.com>
Co-developed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
[sandeen: forward port to modern kernel, fix remounting]
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
cc: "Rafael J. Wysocki" <rafael@kernel.org>
---
 fs/debugfs/inode.c | 198 +++++++++++++++++++++------------------------
 1 file changed, 93 insertions(+), 105 deletions(-)

diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 034a617cb1a5..c2adfb272da8 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -14,7 +14,8 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/mount.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/kobject.h>
@@ -23,7 +24,6 @@
 #include <linux/fsnotify.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
-#include <linux/parser.h>
 #include <linux/magic.h>
 #include <linux/slab.h>
 #include <linux/security.h>
@@ -77,7 +77,7 @@ static struct inode *debugfs_get_inode(struct super_block *sb)
 	return inode;
 }
 
-struct debugfs_mount_opts {
+struct debugfs_fs_info {
 	kuid_t uid;
 	kgid_t gid;
 	umode_t mode;
@@ -89,68 +89,51 @@ enum {
 	Opt_uid,
 	Opt_gid,
 	Opt_mode,
-	Opt_err
 };
 
-static const match_table_t tokens = {
-	{Opt_uid, "uid=%u"},
-	{Opt_gid, "gid=%u"},
-	{Opt_mode, "mode=%o"},
-	{Opt_err, NULL}
+static const struct fs_parameter_spec debugfs_param_specs[] = {
+	fsparam_u32	("gid",		Opt_gid),
+	fsparam_u32oct	("mode",	Opt_mode),
+	fsparam_u32	("uid",		Opt_uid),
+	{}
 };
 
-struct debugfs_fs_info {
-	struct debugfs_mount_opts mount_opts;
-};
-
-static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts)
+static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
-	substring_t args[MAX_OPT_ARGS];
-	int option;
-	int token;
+	struct debugfs_fs_info *opts = fc->s_fs_info;
+	struct fs_parse_result result;
 	kuid_t uid;
 	kgid_t gid;
-	char *p;
-
-	opts->opts = 0;
-	opts->mode = DEBUGFS_DEFAULT_MODE;
-
-	while ((p = strsep(&data, ",")) != NULL) {
-		if (!*p)
-			continue;
-
-		token = match_token(p, tokens, args);
-		switch (token) {
-		case Opt_uid:
-			if (match_int(&args[0], &option))
-				return -EINVAL;
-			uid = make_kuid(current_user_ns(), option);
-			if (!uid_valid(uid))
-				return -EINVAL;
-			opts->uid = uid;
-			break;
-		case Opt_gid:
-			if (match_int(&args[0], &option))
-				return -EINVAL;
-			gid = make_kgid(current_user_ns(), option);
-			if (!gid_valid(gid))
-				return -EINVAL;
-			opts->gid = gid;
-			break;
-		case Opt_mode:
-			if (match_octal(&args[0], &option))
-				return -EINVAL;
-			opts->mode = option & S_IALLUGO;
-			break;
-		/*
-		 * We might like to report bad mount options here;
-		 * but traditionally debugfs has ignored all mount options
-		 */
-		}
-
-		opts->opts |= BIT(token);
+	int opt;
+
+	opt = fs_parse(fc, debugfs_param_specs, param, &result);
+	if (opt < 0)
+		return opt;
+
+	switch (opt) {
+	case Opt_uid:
+		uid = make_kuid(current_user_ns(), result.uint_32);
+		if (!uid_valid(uid))
+			return invalf(fc, "Unknown uid");
+		opts->uid = uid;
+		break;
+	case Opt_gid:
+		gid = make_kgid(current_user_ns(), result.uint_32);
+		if (!gid_valid(gid))
+			return invalf(fc, "Unknown gid");
+		opts->gid = gid;
+		break;
+	case Opt_mode:
+		opts->mode = result.uint_32 & S_IALLUGO;
+		break;
+	/*
+	 * We might like to report bad mount options here;
+	 * but traditionally debugfs has ignored all mount options
+	 */
 	}
 
+	opts->opts |= BIT(opt);
+
 	return 0;
 }
 
@@ -158,23 +141,22 @@ static void _debugfs_apply_options(struct super_block *sb, bool remount)
 {
 	struct debugfs_fs_info *fsi = sb->s_fs_info;
 	struct inode *inode = d_inode(sb->s_root);
-	struct debugfs_mount_opts *opts = &fsi->mount_opts;
 
 	/*
 	 * On remount, only reset mode/uid/gid if they were provided as mount
 	 * options.
 	 */
 
-	if (!remount || opts->opts & BIT(Opt_mode)) {
+	if (!remount || fsi->opts & BIT(Opt_mode)) {
 		inode->i_mode &= ~S_IALLUGO;
-		inode->i_mode |= opts->mode;
+		inode->i_mode |= fsi->mode;
 	}
 
-	if (!remount || opts->opts & BIT(Opt_uid))
-		inode->i_uid = opts->uid;
+	if (!remount || fsi->opts & BIT(Opt_uid))
+		inode->i_uid = fsi->uid;
 
-	if (!remount || opts->opts & BIT(Opt_gid))
-		inode->i_gid = opts->gid;
+	if (!remount || fsi->opts & BIT(Opt_gid))
+		inode->i_gid = fsi->gid;
 }
 
 static void debugfs_apply_options(struct super_block *sb)
@@ -187,35 +169,33 @@ static void debugfs_apply_options_remount(struct super_block *sb)
 	_debugfs_apply_options(sb, true);
 }
 
-static int debugfs_remount(struct super_block *sb, int *flags, char *data)
+static int debugfs_reconfigure(struct fs_context *fc)
 {
-	int err;
-	struct debugfs_fs_info *fsi = sb->s_fs_info;
+	struct super_block *sb = fc->root->d_sb;
+	struct debugfs_fs_info *sb_opts = sb->s_fs_info;
+	struct debugfs_fs_info *new_opts = fc->s_fs_info;
 
 	sync_filesystem(sb);
-	err = debugfs_parse_options(data, &fsi->mount_opts);
-	if (err)
-		goto fail;
 
+	/* structure copy of new mount options to sb */
+	*sb_opts = *new_opts;
 	debugfs_apply_options_remount(sb);
 
-fail:
-	return err;
+	return 0;
 }
 
 static int debugfs_show_options(struct seq_file *m, struct dentry *root)
 {
 	struct debugfs_fs_info *fsi = root->d_sb->s_fs_info;
-	struct debugfs_mount_opts *opts = &fsi->mount_opts;
 
-	if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
+	if (!uid_eq(fsi->uid, GLOBAL_ROOT_UID))
 		seq_printf(m, ",uid=%u",
-			   from_kuid_munged(&init_user_ns, opts->uid));
-	if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
+			   from_kuid_munged(&init_user_ns, fsi->uid));
+	if (!gid_eq(fsi->gid, GLOBAL_ROOT_GID))
 		seq_printf(m, ",gid=%u",
-			   from_kgid_munged(&init_user_ns, opts->gid));
-	if (opts->mode != DEBUGFS_DEFAULT_MODE)
-		seq_printf(m, ",mode=%o", opts->mode);
+			   from_kgid_munged(&init_user_ns, fsi->gid));
+	if (fsi->mode != DEBUGFS_DEFAULT_MODE)
+		seq_printf(m, ",mode=%o", fsi->mode);
 
 	return 0;
 }
@@ -229,7 +209,6 @@ static void debugfs_free_inode(struct inode *inode)
 
 static const struct super_operations debugfs_super_operations = {
 	.statfs		= simple_statfs,
-	.remount_fs	= debugfs_remount,
 	.show_options	= debugfs_show_options,
 	.free_inode	= debugfs_free_inode,
 };
@@ -263,26 +242,14 @@ static const struct dentry_operations debugfs_dops = {
 	.d_automount = debugfs_automount,
 };
 
-static int debug_fill_super(struct super_block *sb, void *data, int silent)
+static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc)
 {
 	static const struct tree_descr debug_files[] = {{""}};
-	struct debugfs_fs_info *fsi;
 	int err;
 
-	fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL);
-	sb->s_fs_info = fsi;
-	if (!fsi) {
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	err = debugfs_parse_options(data, &fsi->mount_opts);
+	err = simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
 	if (err)
-		goto fail;
-
-	err  =  simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
-	if (err)
-		goto fail;
+		return err;
 
 	sb->s_op = &debugfs_super_operations;
 	sb->s_d_op = &debugfs_dops;
@@ -290,27 +257,48 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent)
 	debugfs_apply_options(sb);
 
 	return 0;
-
-fail:
-	kfree(fsi);
-	sb->s_fs_info = NULL;
-	return err;
 }
 
-static struct dentry *debug_mount(struct file_system_type *fs_type,
-			int flags, const char *dev_name,
-			void *data)
+static int debugfs_get_tree(struct fs_context *fc)
 {
 	if (!(debugfs_allow & DEBUGFS_ALLOW_API))
-		return ERR_PTR(-EPERM);
+		return -EPERM;
+
+	return get_tree_single(fc, debugfs_fill_super);
+}
+
+static void debugfs_free_fc(struct fs_context *fc)
+{
+	kfree(fc->s_fs_info);
+}
 
-	return mount_single(fs_type, flags, data, debug_fill_super);
+static const struct fs_context_operations debugfs_context_ops = {
+	.free		= debugfs_free_fc,
+	.parse_param	= debugfs_parse_param,
+	.get_tree	= debugfs_get_tree,
+	.reconfigure	= debugfs_reconfigure,
+};
+
+static int debugfs_init_fs_context(struct fs_context *fc)
+{
+	struct debugfs_fs_info *fsi;
+
+	fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL);
+	if (!fsi)
+		return -ENOMEM;
+
+	fsi->mode = DEBUGFS_DEFAULT_MODE;
+
+	fc->s_fs_info = fsi;
+	fc->ops = &debugfs_context_ops;
+	return 0;
 }
 
 static struct file_system_type debug_fs_type = {
 	.owner =	THIS_MODULE,
 	.name =		"debugfs",
-	.mount =	debug_mount,
+	.init_fs_context = debugfs_init_fs_context,
+	.parameters =	debugfs_param_specs,
 	.kill_sb =	kill_litter_super,
 };
 MODULE_ALIAS_FS("debugfs");
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/2] vfs: Convert tracefs to use the new mount API
  2024-03-05 23:07 [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API Eric Sandeen
  2024-03-05 23:08 ` [PATCH 1/2] vfs: Convert debugfs to use " Eric Sandeen
@ 2024-03-05 23:09 ` Eric Sandeen
  2024-03-06 21:44   ` Steven Rostedt
  2024-03-06 10:57 ` [PATCH 0/2] vfs: convert debugfs & tracefs to " Christian Brauner
  2024-03-12 14:35 ` Christian Brauner
  3 siblings, 1 reply; 13+ messages in thread
From: Eric Sandeen @ 2024-03-05 23:09 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Steven Rostedt, Greg Kroah-Hartman, Rafael J. Wysocki,
	Christian Brauner, Bill O'Donnell, David Howells

From: David Howells <dhowells@redhat.com>

Convert the tracefs filesystem to the new internal mount API as the old
one will be obsoleted and removed.  This allows greater flexibility in
communication of mount parameters between userspace, the VFS and the
filesystem.

See Documentation/filesystems/mount_api.txt for more information.

Signed-off-by: David Howells <dhowells@redhat.com>
Co-developed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
[sandeen: forward port to modern kernel, fix remounting]
cc: Steven Rostedt <rostedt@goodmis.org>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/tracefs/inode.c | 196 +++++++++++++++++++++------------------------
 1 file changed, 91 insertions(+), 105 deletions(-)

diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index d65ffad4c327..69d0fb2e03a2 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -11,14 +11,14 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/mount.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
 #include <linux/kobject.h>
 #include <linux/namei.h>
 #include <linux/tracefs.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
 #include <linux/seq_file.h>
-#include <linux/parser.h>
 #include <linux/magic.h>
 #include <linux/slab.h>
 #include "internal.h"
@@ -231,7 +231,7 @@ struct inode *tracefs_get_inode(struct super_block *sb)
 	return inode;
 }
 
-struct tracefs_mount_opts {
+struct tracefs_fs_info {
 	kuid_t uid;
 	kgid_t gid;
 	umode_t mode;
@@ -243,68 +243,51 @@ enum {
 	Opt_uid,
 	Opt_gid,
 	Opt_mode,
-	Opt_err
 };
 
-static const match_table_t tokens = {
-	{Opt_uid, "uid=%u"},
-	{Opt_gid, "gid=%u"},
-	{Opt_mode, "mode=%o"},
-	{Opt_err, NULL}
+static const struct fs_parameter_spec tracefs_param_specs[] = {
+	fsparam_u32	("gid",		Opt_gid),
+	fsparam_u32oct	("mode",	Opt_mode),
+	fsparam_u32	("uid",		Opt_uid),
+	{}
 };
 
-struct tracefs_fs_info {
-	struct tracefs_mount_opts mount_opts;
-};
-
-static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts)
+static int tracefs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
-	substring_t args[MAX_OPT_ARGS];
-	int option;
-	int token;
+	struct tracefs_fs_info *opts = fc->s_fs_info;
+	struct fs_parse_result result;
 	kuid_t uid;
 	kgid_t gid;
-	char *p;
-
-	opts->opts = 0;
-	opts->mode = TRACEFS_DEFAULT_MODE;
-
-	while ((p = strsep(&data, ",")) != NULL) {
-		if (!*p)
-			continue;
-
-		token = match_token(p, tokens, args);
-		switch (token) {
-		case Opt_uid:
-			if (match_int(&args[0], &option))
-				return -EINVAL;
-			uid = make_kuid(current_user_ns(), option);
-			if (!uid_valid(uid))
-				return -EINVAL;
-			opts->uid = uid;
-			break;
-		case Opt_gid:
-			if (match_int(&args[0], &option))
-				return -EINVAL;
-			gid = make_kgid(current_user_ns(), option);
-			if (!gid_valid(gid))
-				return -EINVAL;
-			opts->gid = gid;
-			break;
-		case Opt_mode:
-			if (match_octal(&args[0], &option))
-				return -EINVAL;
-			opts->mode = option & S_IALLUGO;
-			break;
-		/*
-		 * We might like to report bad mount options here;
-		 * but traditionally tracefs has ignored all mount options
-		 */
-		}
-
-		opts->opts |= BIT(token);
+	int opt;
+
+	opt = fs_parse(fc, tracefs_param_specs, param, &result);
+	if (opt < 0)
+		return opt;
+
+	switch (opt) {
+	case Opt_uid:
+		uid = make_kuid(current_user_ns(), result.uint_32);
+		if (!uid_valid(uid))
+			return invalf(fc, "Unknown uid");
+		opts->uid = uid;
+		break;
+	case Opt_gid:
+		gid = make_kgid(current_user_ns(), result.uint_32);
+		if (!gid_valid(gid))
+			return invalf(fc, "Unknown gid");
+		opts->gid = gid;
+		break;
+	case Opt_mode:
+		opts->mode = result.uint_32 & S_IALLUGO;
+		break;
+	/*
+	 * We might like to report bad mount options here;
+	 * but traditionally tracefs has ignored all mount options
+	 */
 	}
 
+	opts->opts |= BIT(opt);
+
 	return 0;
 }
 
@@ -312,7 +295,6 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
 {
 	struct tracefs_fs_info *fsi = sb->s_fs_info;
 	struct inode *inode = d_inode(sb->s_root);
-	struct tracefs_mount_opts *opts = &fsi->mount_opts;
 	umode_t tmp_mode;
 
 	/*
@@ -320,50 +302,46 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
 	 * options.
 	 */
 
-	if (!remount || opts->opts & BIT(Opt_mode)) {
+	if (!remount || fsi->opts & BIT(Opt_mode)) {
 		tmp_mode = READ_ONCE(inode->i_mode) & ~S_IALLUGO;
-		tmp_mode |= opts->mode;
+		tmp_mode |= fsi->mode;
 		WRITE_ONCE(inode->i_mode, tmp_mode);
 	}
 
-	if (!remount || opts->opts & BIT(Opt_uid))
-		inode->i_uid = opts->uid;
+	if (!remount || fsi->opts & BIT(Opt_uid))
+		inode->i_uid = fsi->uid;
 
-	if (!remount || opts->opts & BIT(Opt_gid))
-		inode->i_gid = opts->gid;
+	if (!remount || fsi->opts & BIT(Opt_gid))
+		inode->i_gid = fsi->gid;
 
 	return 0;
 }
 
-static int tracefs_remount(struct super_block *sb, int *flags, char *data)
+static int tracefs_reconfigure(struct fs_context *fc)
 {
-	int err;
-	struct tracefs_fs_info *fsi = sb->s_fs_info;
+	struct super_block *sb = fc->root->d_sb;
+	struct tracefs_fs_info *sb_opts = sb->s_fs_info;
+	struct tracefs_fs_info *new_opts = fc->s_fs_info;
 
 	sync_filesystem(sb);
-	err = tracefs_parse_options(data, &fsi->mount_opts);
-	if (err)
-		goto fail;
+	/* structure copy of new mount options to sb */
+	*sb_opts = *new_opts;
 
-	tracefs_apply_options(sb, true);
-
-fail:
-	return err;
+	return tracefs_apply_options(sb, true);
 }
 
 static int tracefs_show_options(struct seq_file *m, struct dentry *root)
 {
 	struct tracefs_fs_info *fsi = root->d_sb->s_fs_info;
-	struct tracefs_mount_opts *opts = &fsi->mount_opts;
 
-	if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
+	if (!uid_eq(fsi->uid, GLOBAL_ROOT_UID))
 		seq_printf(m, ",uid=%u",
-			   from_kuid_munged(&init_user_ns, opts->uid));
-	if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
+			   from_kuid_munged(&init_user_ns, fsi->uid));
+	if (!gid_eq(fsi->gid, GLOBAL_ROOT_GID))
 		seq_printf(m, ",gid=%u",
-			   from_kgid_munged(&init_user_ns, opts->gid));
-	if (opts->mode != TRACEFS_DEFAULT_MODE)
-		seq_printf(m, ",mode=%o", opts->mode);
+			   from_kgid_munged(&init_user_ns, fsi->gid));
+	if (fsi->mode != TRACEFS_DEFAULT_MODE)
+		seq_printf(m, ",mode=%o", fsi->mode);
 
 	return 0;
 }
@@ -373,7 +351,6 @@ static const struct super_operations tracefs_super_operations = {
 	.free_inode     = tracefs_free_inode,
 	.drop_inode     = generic_delete_inode,
 	.statfs		= simple_statfs,
-	.remount_fs	= tracefs_remount,
 	.show_options	= tracefs_show_options,
 };
 
@@ -403,26 +380,14 @@ static const struct dentry_operations tracefs_dentry_operations = {
 	.d_release = tracefs_d_release,
 };
 
-static int trace_fill_super(struct super_block *sb, void *data, int silent)
+static int tracefs_fill_super(struct super_block *sb, struct fs_context *fc)
 {
 	static const struct tree_descr trace_files[] = {{""}};
-	struct tracefs_fs_info *fsi;
 	int err;
 
-	fsi = kzalloc(sizeof(struct tracefs_fs_info), GFP_KERNEL);
-	sb->s_fs_info = fsi;
-	if (!fsi) {
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	err = tracefs_parse_options(data, &fsi->mount_opts);
-	if (err)
-		goto fail;
-
-	err  =  simple_fill_super(sb, TRACEFS_MAGIC, trace_files);
+	err = simple_fill_super(sb, TRACEFS_MAGIC, trace_files);
 	if (err)
-		goto fail;
+		return err;
 
 	sb->s_op = &tracefs_super_operations;
 	sb->s_d_op = &tracefs_dentry_operations;
@@ -430,24 +395,45 @@ static int trace_fill_super(struct super_block *sb, void *data, int silent)
 	tracefs_apply_options(sb, false);
 
 	return 0;
+}
 
-fail:
-	kfree(fsi);
-	sb->s_fs_info = NULL;
-	return err;
+static int tracefs_get_tree(struct fs_context *fc)
+{
+	return get_tree_single(fc, tracefs_fill_super);
 }
 
-static struct dentry *trace_mount(struct file_system_type *fs_type,
-			int flags, const char *dev_name,
-			void *data)
+static void tracefs_free_fc(struct fs_context *fc)
 {
-	return mount_single(fs_type, flags, data, trace_fill_super);
+	kfree(fc->s_fs_info);
+}
+
+static const struct fs_context_operations tracefs_context_ops = {
+	.free		= tracefs_free_fc,
+	.parse_param	= tracefs_parse_param,
+	.get_tree	= tracefs_get_tree,
+	.reconfigure	= tracefs_reconfigure,
+};
+
+static int tracefs_init_fs_context(struct fs_context *fc)
+{
+	struct tracefs_fs_info *fsi;
+
+	fsi = kzalloc(sizeof(struct tracefs_fs_info), GFP_KERNEL);
+	if (!fsi)
+		return -ENOMEM;
+
+	fsi->mode = TRACEFS_DEFAULT_MODE;
+
+	fc->s_fs_info = fsi;
+	fc->ops = &tracefs_context_ops;
+	return 0;
 }
 
 static struct file_system_type trace_fs_type = {
 	.owner =	THIS_MODULE,
 	.name =		"tracefs",
-	.mount =	trace_mount,
+	.init_fs_context = tracefs_init_fs_context,
+	.parameters	= tracefs_param_specs,
 	.kill_sb =	kill_litter_super,
 };
 MODULE_ALIAS_FS("tracefs");
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-05 23:08 ` [PATCH 1/2] vfs: Convert debugfs to use " Eric Sandeen
@ 2024-03-06 10:50   ` Christian Brauner
  2024-03-06 12:13     ` Miklos Szeredi
  2024-03-07 21:10   ` Greg Kroah-Hartman
  1 sibling, 1 reply; 13+ messages in thread
From: Christian Brauner @ 2024-03-06 10:50 UTC (permalink / raw)
  To: Eric Sandeen
  Cc: linux-fsdevel, Steven Rostedt, Greg Kroah-Hartman,
	Rafael J. Wysocki, Bill O'Donnell, David Howells

On Tue, Mar 05, 2024 at 05:08:39PM -0600, Eric Sandeen wrote:
> From: David Howells <dhowells@redhat.com>
> 
> Convert the debugfs filesystem to the new internal mount API as the old
> one will be obsoleted and removed.  This allows greater flexibility in
> communication of mount parameters between userspace, the VFS and the
> filesystem.
> 
> See Documentation/filesystems/mount_api.txt for more information.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> Co-developed-by: Eric Sandeen <sandeen@redhat.com>
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
> [sandeen: forward port to modern kernel, fix remounting]
> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> cc: "Rafael J. Wysocki" <rafael@kernel.org>
> ---
>  fs/debugfs/inode.c | 198 +++++++++++++++++++++------------------------
>  1 file changed, 93 insertions(+), 105 deletions(-)
> 
> diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
> index 034a617cb1a5..c2adfb272da8 100644
> --- a/fs/debugfs/inode.c
> +++ b/fs/debugfs/inode.c
> @@ -14,7 +14,8 @@
>  
>  #include <linux/module.h>
>  #include <linux/fs.h>
> -#include <linux/mount.h>
> +#include <linux/fs_context.h>
> +#include <linux/fs_parser.h>
>  #include <linux/pagemap.h>
>  #include <linux/init.h>
>  #include <linux/kobject.h>
> @@ -23,7 +24,6 @@
>  #include <linux/fsnotify.h>
>  #include <linux/string.h>
>  #include <linux/seq_file.h>
> -#include <linux/parser.h>
>  #include <linux/magic.h>
>  #include <linux/slab.h>
>  #include <linux/security.h>
> @@ -77,7 +77,7 @@ static struct inode *debugfs_get_inode(struct super_block *sb)
>  	return inode;
>  }
>  
> -struct debugfs_mount_opts {
> +struct debugfs_fs_info {
>  	kuid_t uid;
>  	kgid_t gid;
>  	umode_t mode;
> @@ -89,68 +89,51 @@ enum {
>  	Opt_uid,
>  	Opt_gid,
>  	Opt_mode,
> -	Opt_err
>  };
>  
> -static const match_table_t tokens = {
> -	{Opt_uid, "uid=%u"},
> -	{Opt_gid, "gid=%u"},
> -	{Opt_mode, "mode=%o"},
> -	{Opt_err, NULL}
> +static const struct fs_parameter_spec debugfs_param_specs[] = {
> +	fsparam_u32	("gid",		Opt_gid),
> +	fsparam_u32oct	("mode",	Opt_mode),
> +	fsparam_u32	("uid",		Opt_uid),
> +	{}
>  };
>  
> -struct debugfs_fs_info {
> -	struct debugfs_mount_opts mount_opts;
> -};
> -
> -static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts)
> +static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
>  {
> -	substring_t args[MAX_OPT_ARGS];
> -	int option;
> -	int token;
> +	struct debugfs_fs_info *opts = fc->s_fs_info;
> +	struct fs_parse_result result;
>  	kuid_t uid;
>  	kgid_t gid;
> -	char *p;
> -
> -	opts->opts = 0;
> -	opts->mode = DEBUGFS_DEFAULT_MODE;
> -
> -	while ((p = strsep(&data, ",")) != NULL) {
> -		if (!*p)
> -			continue;
> -
> -		token = match_token(p, tokens, args);
> -		switch (token) {
> -		case Opt_uid:
> -			if (match_int(&args[0], &option))
> -				return -EINVAL;
> -			uid = make_kuid(current_user_ns(), option);
> -			if (!uid_valid(uid))
> -				return -EINVAL;
> -			opts->uid = uid;
> -			break;
> -		case Opt_gid:
> -			if (match_int(&args[0], &option))
> -				return -EINVAL;
> -			gid = make_kgid(current_user_ns(), option);
> -			if (!gid_valid(gid))
> -				return -EINVAL;
> -			opts->gid = gid;
> -			break;
> -		case Opt_mode:
> -			if (match_octal(&args[0], &option))
> -				return -EINVAL;
> -			opts->mode = option & S_IALLUGO;
> -			break;
> -		/*
> -		 * We might like to report bad mount options here;
> -		 * but traditionally debugfs has ignored all mount options
> -		 */
> -		}
> -
> -		opts->opts |= BIT(token);
> +	int opt;
> +
> +	opt = fs_parse(fc, debugfs_param_specs, param, &result);
> +	if (opt < 0)
> +		return opt;
> +
> +	switch (opt) {
> +	case Opt_uid:
> +		uid = make_kuid(current_user_ns(), result.uint_32);
> +		if (!uid_valid(uid))
> +			return invalf(fc, "Unknown uid");

Fwiw, Opt_{g,u}d I would like to see that either moved completely to the
VFS or we need to provide standardized helpers.

The issue is that for a userns mountable filesytems the validation done
here isn't enough and that's easy to miss (Obviously, debugfs isn't
relevant as it's not userns mountable but still.). For example, for
in tmpfs I recently fixed a bug where validation was wrong:

        case Opt_uid:
                kuid = make_kuid(current_user_ns(), result.uint_32);
                if (!uid_valid(kuid))
                        goto bad_value;

                /*
                 * The requested uid must be representable in the
                 * filesystem's idmapping.
                 */
                if (!kuid_has_mapping(fc->user_ns, kuid))
                        goto bad_value;

                ctx->uid = kuid;
                break;

The crucial step where the {g,u}id must also be representable in the
superblock's namespace not just in the caller's was missing. So really
we should have a generic helper that we can reycle for all Opt_{g,u}id
mount options or move that Opt_{g,u}id to the VFS itself. There was some
nastiness involved in this when I last looked at this though. And all
that invalfc() reporting should then also be identical across
filesystems.

So that's a ToDo for the future.

> +		opts->uid = uid;
> +		break;
> +	case Opt_gid:
> +		gid = make_kgid(current_user_ns(), result.uint_32);
> +		if (!gid_valid(gid))
> +			return invalf(fc, "Unknown gid");
> +		opts->gid = gid;
> +		break;
> +	case Opt_mode:
> +		opts->mode = result.uint_32 & S_IALLUGO;
> +		break;
> +	/*
> +	 * We might like to report bad mount options here;
> +	 * but traditionally debugfs has ignored all mount options
> +	 */
>  	}

We can actually differentiate this. During superblock creation and
remount we're now setting fc->oldapi e.g., what I've done for btrfs in
fs/btrfs/super.c:btrfs_reconfigure_for_mount() or what I did for
fs/overlayfs/params.c:ovl_parse_param().

There's a tiny wrinkle though. We currently have no way of letting
userspace know whether a filesystem supports the new mount API or not
(see that mount option probing systemd does we recently discussed). So
if say mount(8) remounts debugfs with mount options that were ignored in
the old mount api that are now rejected in the new mount api users now
see failures they didn't see before.

For the user it's completely intransparent why that failure happens. For
them nothing changed from util-linux's perspective. So really, we should
probably continue to ignore old mount options for backward compatibility.

>  
> +	opts->opts |= BIT(opt);
> +
>  	return 0;
>  }
>  
> @@ -158,23 +141,22 @@ static void _debugfs_apply_options(struct super_block *sb, bool remount)
>  {
>  	struct debugfs_fs_info *fsi = sb->s_fs_info;
>  	struct inode *inode = d_inode(sb->s_root);
> -	struct debugfs_mount_opts *opts = &fsi->mount_opts;
>  
>  	/*
>  	 * On remount, only reset mode/uid/gid if they were provided as mount
>  	 * options.
>  	 */
>  
> -	if (!remount || opts->opts & BIT(Opt_mode)) {
> +	if (!remount || fsi->opts & BIT(Opt_mode)) {
>  		inode->i_mode &= ~S_IALLUGO;
> -		inode->i_mode |= opts->mode;
> +		inode->i_mode |= fsi->mode;
>  	}
>  
> -	if (!remount || opts->opts & BIT(Opt_uid))
> -		inode->i_uid = opts->uid;
> +	if (!remount || fsi->opts & BIT(Opt_uid))
> +		inode->i_uid = fsi->uid;
>  
> -	if (!remount || opts->opts & BIT(Opt_gid))
> -		inode->i_gid = opts->gid;
> +	if (!remount || fsi->opts & BIT(Opt_gid))
> +		inode->i_gid = fsi->gid;
>  }
>  
>  static void debugfs_apply_options(struct super_block *sb)
> @@ -187,35 +169,33 @@ static void debugfs_apply_options_remount(struct super_block *sb)
>  	_debugfs_apply_options(sb, true);
>  }
>  
> -static int debugfs_remount(struct super_block *sb, int *flags, char *data)
> +static int debugfs_reconfigure(struct fs_context *fc)
>  {
> -	int err;
> -	struct debugfs_fs_info *fsi = sb->s_fs_info;
> +	struct super_block *sb = fc->root->d_sb;
> +	struct debugfs_fs_info *sb_opts = sb->s_fs_info;
> +	struct debugfs_fs_info *new_opts = fc->s_fs_info;
>  
>  	sync_filesystem(sb);
> -	err = debugfs_parse_options(data, &fsi->mount_opts);
> -	if (err)
> -		goto fail;
>  
> +	/* structure copy of new mount options to sb */
> +	*sb_opts = *new_opts;
>  	debugfs_apply_options_remount(sb);
>  
> -fail:
> -	return err;
> +	return 0;
>  }
>  
>  static int debugfs_show_options(struct seq_file *m, struct dentry *root)
>  {
>  	struct debugfs_fs_info *fsi = root->d_sb->s_fs_info;
> -	struct debugfs_mount_opts *opts = &fsi->mount_opts;
>  
> -	if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
> +	if (!uid_eq(fsi->uid, GLOBAL_ROOT_UID))
>  		seq_printf(m, ",uid=%u",
> -			   from_kuid_munged(&init_user_ns, opts->uid));
> -	if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
> +			   from_kuid_munged(&init_user_ns, fsi->uid));
> +	if (!gid_eq(fsi->gid, GLOBAL_ROOT_GID))
>  		seq_printf(m, ",gid=%u",
> -			   from_kgid_munged(&init_user_ns, opts->gid));
> -	if (opts->mode != DEBUGFS_DEFAULT_MODE)
> -		seq_printf(m, ",mode=%o", opts->mode);
> +			   from_kgid_munged(&init_user_ns, fsi->gid));
> +	if (fsi->mode != DEBUGFS_DEFAULT_MODE)
> +		seq_printf(m, ",mode=%o", fsi->mode);
>  
>  	return 0;
>  }
> @@ -229,7 +209,6 @@ static void debugfs_free_inode(struct inode *inode)
>  
>  static const struct super_operations debugfs_super_operations = {
>  	.statfs		= simple_statfs,
> -	.remount_fs	= debugfs_remount,
>  	.show_options	= debugfs_show_options,
>  	.free_inode	= debugfs_free_inode,
>  };
> @@ -263,26 +242,14 @@ static const struct dentry_operations debugfs_dops = {
>  	.d_automount = debugfs_automount,
>  };
>  
> -static int debug_fill_super(struct super_block *sb, void *data, int silent)
> +static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc)
>  {
>  	static const struct tree_descr debug_files[] = {{""}};
> -	struct debugfs_fs_info *fsi;
>  	int err;
>  
> -	fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL);
> -	sb->s_fs_info = fsi;
> -	if (!fsi) {
> -		err = -ENOMEM;
> -		goto fail;
> -	}
> -
> -	err = debugfs_parse_options(data, &fsi->mount_opts);
> +	err = simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
>  	if (err)
> -		goto fail;
> -
> -	err  =  simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
> -	if (err)
> -		goto fail;
> +		return err;
>  
>  	sb->s_op = &debugfs_super_operations;
>  	sb->s_d_op = &debugfs_dops;
> @@ -290,27 +257,48 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent)
>  	debugfs_apply_options(sb);
>  
>  	return 0;
> -
> -fail:
> -	kfree(fsi);
> -	sb->s_fs_info = NULL;
> -	return err;
>  }
>  
> -static struct dentry *debug_mount(struct file_system_type *fs_type,
> -			int flags, const char *dev_name,
> -			void *data)
> +static int debugfs_get_tree(struct fs_context *fc)
>  {
>  	if (!(debugfs_allow & DEBUGFS_ALLOW_API))
> -		return ERR_PTR(-EPERM);
> +		return -EPERM;
> +
> +	return get_tree_single(fc, debugfs_fill_super);
> +}
> +
> +static void debugfs_free_fc(struct fs_context *fc)
> +{
> +	kfree(fc->s_fs_info);
> +}
>  
> -	return mount_single(fs_type, flags, data, debug_fill_super);
> +static const struct fs_context_operations debugfs_context_ops = {
> +	.free		= debugfs_free_fc,
> +	.parse_param	= debugfs_parse_param,
> +	.get_tree	= debugfs_get_tree,
> +	.reconfigure	= debugfs_reconfigure,
> +};
> +
> +static int debugfs_init_fs_context(struct fs_context *fc)
> +{
> +	struct debugfs_fs_info *fsi;
> +
> +	fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL);
> +	if (!fsi)
> +		return -ENOMEM;
> +
> +	fsi->mode = DEBUGFS_DEFAULT_MODE;
> +
> +	fc->s_fs_info = fsi;
> +	fc->ops = &debugfs_context_ops;
> +	return 0;
>  }
>  
>  static struct file_system_type debug_fs_type = {
>  	.owner =	THIS_MODULE,
>  	.name =		"debugfs",
> -	.mount =	debug_mount,
> +	.init_fs_context = debugfs_init_fs_context,
> +	.parameters =	debugfs_param_specs,
>  	.kill_sb =	kill_litter_super,
>  };
>  MODULE_ALIAS_FS("debugfs");
> -- 
> 2.43.0
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API
  2024-03-05 23:07 [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API Eric Sandeen
  2024-03-05 23:08 ` [PATCH 1/2] vfs: Convert debugfs to use " Eric Sandeen
  2024-03-05 23:09 ` [PATCH 2/2] vfs: Convert tracefs " Eric Sandeen
@ 2024-03-06 10:57 ` Christian Brauner
  2024-03-12 14:35 ` Christian Brauner
  3 siblings, 0 replies; 13+ messages in thread
From: Christian Brauner @ 2024-03-06 10:57 UTC (permalink / raw)
  To: Eric Sandeen
  Cc: linux-fsdevel, Steven Rostedt, Greg Kroah-Hartman,
	Rafael J. Wysocki, Bill O'Donnell, David Howells

On Tue, Mar 05, 2024 at 05:07:29PM -0600, Eric Sandeen wrote:
> Since debugfs and tracefs are cut & pasted one way or the other,
> do these at the same time.
> 
> Both of these patches originated in dhowells' tree at
> https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=mount-api-viro
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=mount-api-viro&id=ec14be9e2aa76f63458466bba86256e123ec4e51
> and
> https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=mount-api-viro&id=c4f2e60465859e02a6e36ed618dbaea16de8c8e0
> 
> I've forward-ported them to the mount API that landed, and
> fixed up remounting; ->reconfigure() needed to copy the
> parsed context options into the current superblock options
> to effect any remount changes.
> 
> While these do use the invalf() functions for some errors, they
> are new messages, not messages that used to go to dmesg that
> would be lost if userspace isn't listening.
> 
> I've done minimal testing - booting with the patches, testing
> some of the remount behavior for mode & uid.
> Oh, and I built it too. </brown_paper_bag>

Looks ok to me.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-06 10:50   ` Christian Brauner
@ 2024-03-06 12:13     ` Miklos Szeredi
  2024-03-06 12:17       ` Christian Brauner
  0 siblings, 1 reply; 13+ messages in thread
From: Miklos Szeredi @ 2024-03-06 12:13 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Eric Sandeen, linux-fsdevel, Steven Rostedt, Greg Kroah-Hartman,
	Rafael J. Wysocki, Bill O'Donnell, David Howells

On Wed, 6 Mar 2024 at 11:57, Christian Brauner <brauner@kernel.org> wrote:

> There's a tiny wrinkle though. We currently have no way of letting
> userspace know whether a filesystem supports the new mount API or not
> (see that mount option probing systemd does we recently discussed). So
> if say mount(8) remounts debugfs with mount options that were ignored in
> the old mount api that are now rejected in the new mount api users now
> see failures they didn't see before.
>
> For the user it's completely intransparent why that failure happens. For
> them nothing changed from util-linux's perspective. So really, we should
> probably continue to ignore old mount options for backward compatibility.

The reject behavior could be made conditional on e.g. an fsopen() flag.

I.e. FSOPEN_REJECT_UNKNOWN would make unknown options be always
rejected.  Without this flag fsconfig(2) would behave identically
before/after the conversion.

Thanks,
Miklos

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-06 12:13     ` Miklos Szeredi
@ 2024-03-06 12:17       ` Christian Brauner
  2024-03-06 16:35         ` Eric Sandeen
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Brauner @ 2024-03-06 12:17 UTC (permalink / raw)
  To: Miklos Szeredi
  Cc: Eric Sandeen, linux-fsdevel, Steven Rostedt, Greg Kroah-Hartman,
	Rafael J. Wysocki, Bill O'Donnell, David Howells

On Wed, Mar 06, 2024 at 01:13:05PM +0100, Miklos Szeredi wrote:
> On Wed, 6 Mar 2024 at 11:57, Christian Brauner <brauner@kernel.org> wrote:
> 
> > There's a tiny wrinkle though. We currently have no way of letting
> > userspace know whether a filesystem supports the new mount API or not
> > (see that mount option probing systemd does we recently discussed). So
> > if say mount(8) remounts debugfs with mount options that were ignored in
> > the old mount api that are now rejected in the new mount api users now
> > see failures they didn't see before.
> >
> > For the user it's completely intransparent why that failure happens. For
> > them nothing changed from util-linux's perspective. So really, we should
> > probably continue to ignore old mount options for backward compatibility.
> 
> The reject behavior could be made conditional on e.g. an fsopen() flag.

and fspick() which I think is more relevant.

> 
> I.e. FSOPEN_REJECT_UNKNOWN would make unknown options be always
> rejected.  Without this flag fsconfig(2) would behave identically
> before/after the conversion.

Yeah, that would work. That would only make sense if we make all
filesystems reject unknown mount options by default when they're
switched to the new mount api imho. When we recognize the request comes
from the old mount api fc->oldapi we continue ignoring as we did before.
If it comes from the new mount api we reject unless
FSOPEN/FSPICK_REJECT_UKNOWN was specified.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-06 12:17       ` Christian Brauner
@ 2024-03-06 16:35         ` Eric Sandeen
  2024-03-07 12:04           ` Christian Brauner
  0 siblings, 1 reply; 13+ messages in thread
From: Eric Sandeen @ 2024-03-06 16:35 UTC (permalink / raw)
  To: Christian Brauner, Miklos Szeredi
  Cc: Eric Sandeen, linux-fsdevel, Steven Rostedt, Greg Kroah-Hartman,
	Rafael J. Wysocki, Bill O'Donnell, David Howells

On 3/6/24 6:17 AM, Christian Brauner wrote:
> On Wed, Mar 06, 2024 at 01:13:05PM +0100, Miklos Szeredi wrote:
>> On Wed, 6 Mar 2024 at 11:57, Christian Brauner <brauner@kernel.org> wrote:
>>
>>> There's a tiny wrinkle though. We currently have no way of letting
>>> userspace know whether a filesystem supports the new mount API or not
>>> (see that mount option probing systemd does we recently discussed). So
>>> if say mount(8) remounts debugfs with mount options that were ignored in
>>> the old mount api that are now rejected in the new mount api users now
>>> see failures they didn't see before.

Oh, right - the problem is the new mount API rejects unknown options
internally, right?

>>> For the user it's completely intransparent why that failure happens. For
>>> them nothing changed from util-linux's perspective. So really, we should
>>> probably continue to ignore old mount options for backward compatibility.
>>
>> The reject behavior could be made conditional on e.g. an fsopen() flag.
> 
> and fspick() which I think is more relevant.
> 
>>
>> I.e. FSOPEN_REJECT_UNKNOWN would make unknown options be always
>> rejected.  Without this flag fsconfig(2) would behave identically
>> before/after the conversion.
> 
> Yeah, that would work. That would only make sense if we make all
> filesystems reject unknown mount options by default when they're
> switched to the new mount api imho. When we recognize the request comes
> from the old mount api fc->oldapi we continue ignoring as we did before.
> If it comes from the new mount api we reject unless
> FSOPEN/FSPICK_REJECT_UKNOWN was specified.

Ok, good point. Just thinking out loud, I guess an fsopen/fspick flag does
make more sense than i.e. each filesystem deciding whether it should reject
unknown options in its ->init_fs_context(), for consistency?

Right now it looks like the majority of filesystems do reject unknown
options internally, already.

(To muddy the waters more, other inconsistencies I've thought about are
re: how the fileystem handles remount. For example, which options are
remountable and which are not, and should non-remountable options fail?
Also whether the filesystem internally preserves the original set of
options and applies the new set as a delta, or whether it treats the
new set as the exact set of options requested post-remount, but that's
probably a topic for another day.)

-Eric

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] vfs: Convert tracefs to use the new mount API
  2024-03-05 23:09 ` [PATCH 2/2] vfs: Convert tracefs " Eric Sandeen
@ 2024-03-06 21:44   ` Steven Rostedt
  0 siblings, 0 replies; 13+ messages in thread
From: Steven Rostedt @ 2024-03-06 21:44 UTC (permalink / raw)
  To: Eric Sandeen
  Cc: linux-fsdevel, Greg Kroah-Hartman, Rafael J. Wysocki,
	Christian Brauner, Bill O'Donnell, David Howells

On Tue, 5 Mar 2024 17:09:30 -0600
Eric Sandeen <sandeen@redhat.com> (by way of Steven Rostedt <rostedt@goodmis.org>) wrote:

> From: David Howells <dhowells@redhat.com>
> 
> Convert the tracefs filesystem to the new internal mount API as the old
> one will be obsoleted and removed.  This allows greater flexibility in
> communication of mount parameters between userspace, the VFS and the
> filesystem.
> 
> See Documentation/filesystems/mount_api.txt for more information.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> Co-developed-by: Eric Sandeen <sandeen@redhat.com>
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
> [sandeen: forward port to modern kernel, fix remounting]
> cc: Steven Rostedt <rostedt@goodmis.org>
> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>

I applied this and ran it through all my tests and it passed.

Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Tested-by: Steven Rostedt (Google) <rostedt@goodmis.org>

-- Steve

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-06 16:35         ` Eric Sandeen
@ 2024-03-07 12:04           ` Christian Brauner
  2024-03-08 14:54             ` Miklos Szeredi
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Brauner @ 2024-03-07 12:04 UTC (permalink / raw)
  To: Eric Sandeen
  Cc: Miklos Szeredi, Eric Sandeen, linux-fsdevel, Steven Rostedt,
	Greg Kroah-Hartman, Rafael J. Wysocki, Bill O'Donnell,
	David Howells

On Wed, Mar 06, 2024 at 10:35:02AM -0600, Eric Sandeen wrote:
> On 3/6/24 6:17 AM, Christian Brauner wrote:
> > On Wed, Mar 06, 2024 at 01:13:05PM +0100, Miklos Szeredi wrote:
> >> On Wed, 6 Mar 2024 at 11:57, Christian Brauner <brauner@kernel.org> wrote:
> >>
> >>> There's a tiny wrinkle though. We currently have no way of letting
> >>> userspace know whether a filesystem supports the new mount API or not
> >>> (see that mount option probing systemd does we recently discussed). So
> >>> if say mount(8) remounts debugfs with mount options that were ignored in
> >>> the old mount api that are now rejected in the new mount api users now
> >>> see failures they didn't see before.
> 
> Oh, right - the problem is the new mount API rejects unknown options
> internally, right?
> 
> >>> For the user it's completely intransparent why that failure happens. For
> >>> them nothing changed from util-linux's perspective. So really, we should
> >>> probably continue to ignore old mount options for backward compatibility.
> >>
> >> The reject behavior could be made conditional on e.g. an fsopen() flag.
> > 
> > and fspick() which I think is more relevant.
> > 
> >>
> >> I.e. FSOPEN_REJECT_UNKNOWN would make unknown options be always
> >> rejected.  Without this flag fsconfig(2) would behave identically
> >> before/after the conversion.
> > 
> > Yeah, that would work. That would only make sense if we make all
> > filesystems reject unknown mount options by default when they're
> > switched to the new mount api imho. When we recognize the request comes
> > from the old mount api fc->oldapi we continue ignoring as we did before.
> > If it comes from the new mount api we reject unless
> > FSOPEN/FSPICK_REJECT_UKNOWN was specified.

I actually did misparse that I now realize. I read that as "ignore
unknown" instead of "reject unknown".

> 
> Ok, good point. Just thinking out loud, I guess an fsopen/fspick flag does
> make more sense than i.e. each filesystem deciding whether it should reject
> unknown options in its ->init_fs_context(), for consistency?

Yes, I think so. The interesting case for util-linux according to Karel
was remounting where mount(8) wants to gather all options from fstab and
mountinfo, add new options from the command line and send it to the
kernel without having to care about filesystems specific options that
cannot be changed on remount.

However, other users that do use the api programatically do care about
this. They want to get an error when changing a mount property doesn't
work.

I think doing this on a per-fs basis just leads to more inconsistency.
I'd rather have this be something we enforce on a higher level if we do
it at all.

> 
> Right now it looks like the majority of filesystems do reject unknown
> options internally, already.

Yeah, it's mostly pseudo fses that don't, I reckon.

> 
> (To muddy the waters more, other inconsistencies I've thought about are
> re: how the fileystem handles remount. For example, which options are
> remountable and which are not, and should non-remountable options fail?

Yes, they should but similar to fsopen() we should have an fspick()
flag. This was what I mentioned earlier in my response to Miklos.

But I'm not yet clear whether FSOPEN/FSPICK_IGNORE_UNKNOWN wouldn't make
more sense than FSOPEN/FSPICK_REJECT_UNKNOWN. IOW, invert the logic.

Because as you said most filesystems do already reject unknown mount
options and it's a few that don't. So I think we should focus on the
remount case and for that I think we want FSOPEN_IGNORE_UNKNOWN
otherwise default to rejecting unknown options if coming from the new
mount api? I'm not sure.

> Also whether the filesystem internally preserves the original set of
> options and applies the new set as a delta, or whether it treats the
> new set as the exact set of options requested post-remount, but that's
> probably a topic for another day.)

For vfs mount properties it's a delta in the new mount api. The old
mount api didn't have a concept of add or subtract. If you had a
read-only mount and you wanted to also make it noexec then you'd have to
specify "ro" again otherwise the mount would be made rw. mount(8) hides
that behavior by retrieving the current mountflags from mountinfo and
adding it to the remount call if the old mount api is used.
mount_setattr() does that directly in the kernel and always does a
delta.

For filesystem specific properties it's probably irrelevant because
remount already is effectively a delta for most filesystems. IOW, you
don't suddenly get "usrquota" unset because you've changed the "dax"
property on your xfs filesystem which would be worrisome. :)

The thing is though that changing one mount option might implicitly
change other mount options. But that's something that only the
filesystem should decide. So I don't think this is something we need to
worry about?

The way I see mount(8) currently doing it is to change:

(1) filesystem specific mount properties via fspick()+fsconfig()
(2) generic mount properties via mount_setattr()

during a remount call.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-05 23:08 ` [PATCH 1/2] vfs: Convert debugfs to use " Eric Sandeen
  2024-03-06 10:50   ` Christian Brauner
@ 2024-03-07 21:10   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 13+ messages in thread
From: Greg Kroah-Hartman @ 2024-03-07 21:10 UTC (permalink / raw)
  To: Eric Sandeen
  Cc: linux-fsdevel, Steven Rostedt, Rafael J. Wysocki,
	Christian Brauner, Bill O'Donnell, David Howells

On Tue, Mar 05, 2024 at 05:08:39PM -0600, Eric Sandeen wrote:
> From: David Howells <dhowells@redhat.com>
> 
> Convert the debugfs filesystem to the new internal mount API as the old
> one will be obsoleted and removed.  This allows greater flexibility in
> communication of mount parameters between userspace, the VFS and the
> filesystem.
> 
> See Documentation/filesystems/mount_api.txt for more information.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> Co-developed-by: Eric Sandeen <sandeen@redhat.com>
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
> [sandeen: forward port to modern kernel, fix remounting]
> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> cc: "Rafael J. Wysocki" <rafael@kernel.org>
> ---
>  fs/debugfs/inode.c | 198 +++++++++++++++++++++------------------------
>  1 file changed, 93 insertions(+), 105 deletions(-)

If the vfs maintainers are ok with the conversion, it's fine with me:

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] vfs: Convert debugfs to use the new mount API
  2024-03-07 12:04           ` Christian Brauner
@ 2024-03-08 14:54             ` Miklos Szeredi
  0 siblings, 0 replies; 13+ messages in thread
From: Miklos Szeredi @ 2024-03-08 14:54 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Eric Sandeen, Eric Sandeen, linux-fsdevel, Steven Rostedt,
	Greg Kroah-Hartman, Rafael J. Wysocki, Bill O'Donnell,
	David Howells

On Thu, 7 Mar 2024 at 13:04, Christian Brauner <brauner@kernel.org> wrote:

> But I'm not yet clear whether FSOPEN/FSPICK_IGNORE_UNKNOWN wouldn't make
> more sense than FSOPEN/FSPICK_REJECT_UNKNOWN. IOW, invert the logic.

I think there needs to be a mode for fsopen/fspick/fconfig API that
allows implementing full backward compatibility with the old behavior
of mount(8), both in case of new mount and remount.  By old I mean
before any of the API conversions started.  If some filesystems
rejected unknown options and some ignored them, then that is what this
mode should continue to do.  This is what we currently have, so
without additional flags this is what the API should continue to
support.

And I think there needs to be a new "strict" mode for fsopen/fspick
that has clear rules for how filesystems should handle options, which
as you say most filesystem already do.   Since this is a new mode, I
think it needs a new flag, that is rejected if the API or the fs
doesn't support this mode.  Filesystems which already have sane
behavior need not care, they would work the same in both modes.
Filesystems that are currently inconsistent would have to implement
both modes.

Thanks,
Miklos

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API
  2024-03-05 23:07 [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API Eric Sandeen
                   ` (2 preceding siblings ...)
  2024-03-06 10:57 ` [PATCH 0/2] vfs: convert debugfs & tracefs to " Christian Brauner
@ 2024-03-12 14:35 ` Christian Brauner
  3 siblings, 0 replies; 13+ messages in thread
From: Christian Brauner @ 2024-03-12 14:35 UTC (permalink / raw)
  To: Eric Sandeen, Steven Rostedt, Greg Kroah-Hartman
  Cc: Christian Brauner, Rafael J. Wysocki, Bill O'Donnell,
	David Howells, linux-fsdevel

On Tue, 05 Mar 2024 17:07:29 -0600, Eric Sandeen wrote:
> Since debugfs and tracefs are cut & pasted one way or the other,
> do these at the same time.
> 
> Both of these patches originated in dhowells' tree at
> https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=mount-api-viro
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=mount-api-viro&id=ec14be9e2aa76f63458466bba86256e123ec4e51
> and
> https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=mount-api-viro&id=c4f2e60465859e02a6e36ed618dbaea16de8c8e0
> 
> [...]

I'm assuming that your Acks meant I'm good to pick those up.
Please yell, if not!

---

Applied to the vfs.misc branch of the vfs/vfs.git tree.
Patches in the vfs.misc branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.misc

[1/2] vfs: Convert debugfs to use the new mount API
      https://git.kernel.org/vfs/vfs/c/393b0b4c609e
[2/2] vfs: Convert tracefs to use the new mount API
      https://git.kernel.org/vfs/vfs/c/140a2056102a

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-03-12 14:36 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-05 23:07 [PATCH 0/2] vfs: convert debugfs & tracefs to the new mount API Eric Sandeen
2024-03-05 23:08 ` [PATCH 1/2] vfs: Convert debugfs to use " Eric Sandeen
2024-03-06 10:50   ` Christian Brauner
2024-03-06 12:13     ` Miklos Szeredi
2024-03-06 12:17       ` Christian Brauner
2024-03-06 16:35         ` Eric Sandeen
2024-03-07 12:04           ` Christian Brauner
2024-03-08 14:54             ` Miklos Szeredi
2024-03-07 21:10   ` Greg Kroah-Hartman
2024-03-05 23:09 ` [PATCH 2/2] vfs: Convert tracefs " Eric Sandeen
2024-03-06 21:44   ` Steven Rostedt
2024-03-06 10:57 ` [PATCH 0/2] vfs: convert debugfs & tracefs to " Christian Brauner
2024-03-12 14:35 ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).