* [PATCH 0/4] fs: last of the pseudofs mount api conversions
@ 2025-02-05 21:34 Eric Sandeen
2025-02-05 21:34 ` [PATCH 1/4] pstore: convert to the new mount API Eric Sandeen
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Eric Sandeen @ 2025-02-05 21:34 UTC (permalink / raw)
To: linux-fsdevel, brauner; +Cc: viro, neilb, ebiederm, kees, tony.luck
Notes:
pstore used mount_single, which used to transparently do a
remount operation on a fresh mount of an existing superblock.
The new get_tree_single does not do this, but prior discussion
on fsdevel seems to indicate that this isn't expected to be a
problem. We can watch for issues.
devpts is just a forward port from work dhowells did already, and it
seems straightforward. I left error messages as they are rather than
converting to the mount API message channel for now.
devtmpfs was already converted, but left a .mount in place, rather
than using .get_tree. The solution to this is ... unique so some
scrutiny is probably wise.
The last patch removes reconfigure_single, mount_single, and
compare_single because no users remain, but we could also wait until
all conversions are done, and remove all infrastructure at that time
instead, if desired.
Thanks,
Eric
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] pstore: convert to the new mount API
2025-02-05 21:34 [PATCH 0/4] fs: last of the pseudofs mount api conversions Eric Sandeen
@ 2025-02-05 21:34 ` Eric Sandeen
2025-02-06 2:04 ` Kees Cook
2025-02-05 21:34 ` [PATCH 2/4] vfs: Convert devpts to use " Eric Sandeen
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Eric Sandeen @ 2025-02-05 21:34 UTC (permalink / raw)
To: linux-fsdevel, brauner
Cc: viro, neilb, ebiederm, kees, tony.luck, Eric Sandeen
Convert the pstore filesystem to the new mount API.
Cc: Kees Cook <kees@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
fs/pstore/inode.c | 111 +++++++++++++++++++++++++++++++---------------
1 file changed, 75 insertions(+), 36 deletions(-)
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 56815799ce79..3a4582b79c75 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -14,10 +14,10 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/string.h>
-#include <linux/mount.h>
#include <linux/seq_file.h>
#include <linux/ramfs.h>
-#include <linux/parser.h>
+#include <linux/fs_parser.h>
+#include <linux/fs_context.h>
#include <linux/sched.h>
#include <linux/magic.h>
#include <linux/pstore.h>
@@ -226,37 +226,38 @@ static struct inode *pstore_get_inode(struct super_block *sb)
}
enum {
- Opt_kmsg_bytes, Opt_err
+ Opt_kmsg_bytes
};
-static const match_table_t tokens = {
- {Opt_kmsg_bytes, "kmsg_bytes=%u"},
- {Opt_err, NULL}
+static const struct fs_parameter_spec pstore_param_spec[] = {
+ fsparam_u32 ("kmsg_bytes", Opt_kmsg_bytes),
+ {}
};
-static void parse_options(char *options)
-{
- char *p;
- substring_t args[MAX_OPT_ARGS];
- int option;
-
- if (!options)
- return;
+struct pstore_context {
+ unsigned int kmsg_bytes;
+};
- while ((p = strsep(&options, ",")) != NULL) {
- int token;
+static int pstore_parse_param(struct fs_context *fc, struct fs_parameter *param)
+{
+ struct pstore_context *ctx = fc->fs_private;
+ struct fs_parse_result result;
+ int opt;
- if (!*p)
- continue;
+ opt = fs_parse(fc, pstore_param_spec, param, &result);
+ /* pstore has historically ignored invalid kmsg_bytes param */
+ if (opt < 0)
+ return 0;
- token = match_token(p, tokens, args);
- switch (token) {
- case Opt_kmsg_bytes:
- if (!match_int(&args[0], &option))
- pstore_set_kmsg_bytes(option);
- break;
- }
+ switch (opt) {
+ case Opt_kmsg_bytes:
+ ctx->kmsg_bytes = result.uint_32;
+ break;
+ default:
+ return -EINVAL;
}
+
+ return 0;
}
/*
@@ -269,10 +270,12 @@ static int pstore_show_options(struct seq_file *m, struct dentry *root)
return 0;
}
-static int pstore_remount(struct super_block *sb, int *flags, char *data)
+static int pstore_reconfigure(struct fs_context *fc)
{
- sync_filesystem(sb);
- parse_options(data);
+ struct pstore_context *ctx = fc->fs_private;
+
+ sync_filesystem(fc->root->d_sb);
+ pstore_set_kmsg_bytes(ctx->kmsg_bytes);
return 0;
}
@@ -281,7 +284,6 @@ static const struct super_operations pstore_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
.evict_inode = pstore_evict_inode,
- .remount_fs = pstore_remount,
.show_options = pstore_show_options,
};
@@ -406,8 +408,9 @@ void pstore_get_records(int quiet)
inode_unlock(d_inode(root));
}
-static int pstore_fill_super(struct super_block *sb, void *data, int silent)
+static int pstore_fill_super(struct super_block *sb, struct fs_context *fc)
{
+ struct pstore_context *ctx = fc->fs_private;
struct inode *inode;
sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -417,7 +420,7 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &pstore_ops;
sb->s_time_gran = 1;
- parse_options(data);
+ pstore_set_kmsg_bytes(ctx->kmsg_bytes);
inode = pstore_get_inode(sb);
if (inode) {
@@ -431,19 +434,33 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
return -ENOMEM;
scoped_guard(mutex, &pstore_sb_lock)
- pstore_sb = sb;
+ pstore_sb = sb;
pstore_get_records(0);
return 0;
}
-static struct dentry *pstore_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+static int pstore_get_tree(struct fs_context *fc)
+{
+ if (fc->root)
+ return pstore_reconfigure(fc);
+
+ return get_tree_single(fc, pstore_fill_super);
+}
+
+static void pstore_free_fc(struct fs_context *fc)
{
- return mount_single(fs_type, flags, data, pstore_fill_super);
+ kfree(fc->fs_private);
}
+static const struct fs_context_operations pstore_context_ops = {
+ .parse_param = pstore_parse_param,
+ .get_tree = pstore_get_tree,
+ .reconfigure = pstore_reconfigure,
+ .free = pstore_free_fc,
+};
+
static void pstore_kill_sb(struct super_block *sb)
{
guard(mutex)(&pstore_sb_lock);
@@ -456,11 +473,33 @@ static void pstore_kill_sb(struct super_block *sb)
INIT_LIST_HEAD(&records_list);
}
+static int pstore_init_fs_context(struct fs_context *fc)
+{
+ struct pstore_context *ctx;
+
+ ctx = kzalloc(sizeof(struct pstore_context), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ /*
+ * Global kmsg_bytes is initialized to default, and updated
+ * every time we (re)mount the single-sb filesystem with the
+ * option specified.
+ */
+ ctx->kmsg_bytes = kmsg_bytes;
+
+ fc->fs_private = ctx;
+ fc->ops = &pstore_context_ops;
+
+ return 0;
+}
+
static struct file_system_type pstore_fs_type = {
.owner = THIS_MODULE,
.name = "pstore",
- .mount = pstore_mount,
.kill_sb = pstore_kill_sb,
+ .init_fs_context = pstore_init_fs_context,
+ .parameters = pstore_param_spec,
};
int __init pstore_init_fs(void)
--
2.48.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] vfs: Convert devpts to use the new mount API
2025-02-05 21:34 [PATCH 0/4] fs: last of the pseudofs mount api conversions Eric Sandeen
2025-02-05 21:34 ` [PATCH 1/4] pstore: convert to the new mount API Eric Sandeen
@ 2025-02-05 21:34 ` Eric Sandeen
2025-02-05 21:34 ` [PATCH 3/4] devtmpfs: replace ->mount with ->get_tree in public instance Eric Sandeen
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Eric Sandeen @ 2025-02-05 21:34 UTC (permalink / raw)
To: linux-fsdevel, brauner
Cc: viro, neilb, ebiederm, kees, tony.luck, David Howells,
Eric Sandeen
From: David Howells <dhowells@redhat.com>
Convert the devpts 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.
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David Howells <dhowells@redhat.com>
[sandeen: forward port, keep pr_err vs errorf]
Co-developed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
fs/devpts/inode.c | 251 ++++++++++++++++++++--------------------------
1 file changed, 110 insertions(+), 141 deletions(-)
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 1096ff8562fa..42e4d6eeb29f 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -12,6 +12,8 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
#include <linux/sched.h>
#include <linux/namei.h>
#include <linux/slab.h>
@@ -21,7 +23,6 @@
#include <linux/magic.h>
#include <linux/idr.h>
#include <linux/devpts_fs.h>
-#include <linux/parser.h>
#include <linux/fsnotify.h>
#include <linux/seq_file.h>
@@ -87,14 +88,14 @@ enum {
Opt_err
};
-static const match_table_t tokens = {
- {Opt_uid, "uid=%u"},
- {Opt_gid, "gid=%u"},
- {Opt_mode, "mode=%o"},
- {Opt_ptmxmode, "ptmxmode=%o"},
- {Opt_newinstance, "newinstance"},
- {Opt_max, "max=%d"},
- {Opt_err, NULL}
+static const struct fs_parameter_spec devpts_param_specs[] = {
+ fsparam_u32 ("gid", Opt_gid),
+ fsparam_s32 ("max", Opt_max),
+ fsparam_u32oct ("mode", Opt_mode),
+ fsparam_flag ("newinstance", Opt_newinstance),
+ fsparam_u32oct ("ptmxmode", Opt_ptmxmode),
+ fsparam_u32 ("uid", Opt_uid),
+ {}
};
struct pts_fs_info {
@@ -214,93 +215,48 @@ void devpts_release(struct pts_fs_info *fsi)
deactivate_super(fsi->sb);
}
-#define PARSE_MOUNT 0
-#define PARSE_REMOUNT 1
-
/*
- * parse_mount_options():
- * Set @opts to mount options specified in @data. If an option is not
- * specified in @data, set it to its default value.
- *
- * Note: @data may be NULL (in which case all options are set to default).
+ * devpts_parse_param - Parse mount parameters
*/
-static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
+static int devpts_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
- char *p;
- kuid_t uid;
- kgid_t gid;
-
- opts->setuid = 0;
- opts->setgid = 0;
- opts->uid = GLOBAL_ROOT_UID;
- opts->gid = GLOBAL_ROOT_GID;
- opts->mode = DEVPTS_DEFAULT_MODE;
- opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
- opts->max = NR_UNIX98_PTY_MAX;
-
- /* Only allow instances mounted from the initial mount
- * namespace to tap the reserve pool of ptys.
- */
- if (op == PARSE_MOUNT)
- opts->reserve =
- (current->nsproxy->mnt_ns == init_task.nsproxy->mnt_ns);
-
- while ((p = strsep(&data, ",")) != NULL) {
- substring_t args[MAX_OPT_ARGS];
- int token;
- int option;
-
- 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;
- opts->setuid = 1;
- 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;
- opts->setgid = 1;
- break;
- case Opt_mode:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- opts->mode = option & S_IALLUGO;
- break;
- case Opt_ptmxmode:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- opts->ptmxmode = option & S_IALLUGO;
- break;
- case Opt_newinstance:
- break;
- case Opt_max:
- if (match_int(&args[0], &option) ||
- option < 0 || option > NR_UNIX98_PTY_MAX)
- return -EINVAL;
- opts->max = option;
- break;
- default:
- pr_err("called with bogus options\n");
- return -EINVAL;
- }
+ struct pts_fs_info *fsi = fc->s_fs_info;
+ struct pts_mount_opts *opts = &fsi->mount_opts;
+ struct fs_parse_result result;
+ int opt;
+
+ opt = fs_parse(fc, devpts_param_specs, param, &result);
+ if (opt < 0)
+ return opt;
+
+ switch (opt) {
+ case Opt_uid:
+ opts->uid = result.uid;
+ opts->setuid = 1;
+ break;
+ case Opt_gid:
+ opts->gid = result.gid;
+ opts->setgid = 1;
+ break;
+ case Opt_mode:
+ opts->mode = result.uint_32 & S_IALLUGO;
+ break;
+ case Opt_ptmxmode:
+ opts->ptmxmode = result.uint_32 & S_IALLUGO;
+ break;
+ case Opt_newinstance:
+ break;
+ case Opt_max:
+ if (result.uint_32 > NR_UNIX98_PTY_MAX)
+ return invalf(fc, "max out of range");
+ opts->max = result.uint_32;
+ break;
}
return 0;
}
-static int mknod_ptmx(struct super_block *sb)
+static int mknod_ptmx(struct super_block *sb, struct fs_context *fc)
{
int mode;
int rc = -ENOMEM;
@@ -362,13 +318,23 @@ static void update_ptmx_mode(struct pts_fs_info *fsi)
}
}
-static int devpts_remount(struct super_block *sb, int *flags, char *data)
+static int devpts_reconfigure(struct fs_context *fc)
{
- int err;
- struct pts_fs_info *fsi = DEVPTS_SB(sb);
- struct pts_mount_opts *opts = &fsi->mount_opts;
+ struct pts_fs_info *fsi = DEVPTS_SB(fc->root->d_sb);
+ struct pts_fs_info *new = fc->s_fs_info;
- err = parse_mount_options(data, PARSE_REMOUNT, opts);
+ /* Apply the revised options. We don't want to change ->reserve.
+ * Ideally, we'd update each option conditionally on it having been
+ * explicitly changed, but the default is to reset everything so that
+ * would break UAPI...
+ */
+ fsi->mount_opts.setuid = new->mount_opts.setuid;
+ fsi->mount_opts.setgid = new->mount_opts.setgid;
+ fsi->mount_opts.uid = new->mount_opts.uid;
+ fsi->mount_opts.gid = new->mount_opts.gid;
+ fsi->mount_opts.mode = new->mount_opts.mode;
+ fsi->mount_opts.ptmxmode = new->mount_opts.ptmxmode;
+ fsi->mount_opts.max = new->mount_opts.max;
/*
* parse_mount_options() restores options to default values
@@ -378,7 +344,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data)
*/
update_ptmx_mode(fsi);
- return err;
+ return 0;
}
static int devpts_show_options(struct seq_file *seq, struct dentry *root)
@@ -402,31 +368,13 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root)
static const struct super_operations devpts_sops = {
.statfs = simple_statfs,
- .remount_fs = devpts_remount,
.show_options = devpts_show_options,
};
-static void *new_pts_fs_info(struct super_block *sb)
-{
- struct pts_fs_info *fsi;
-
- fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
- if (!fsi)
- return NULL;
-
- ida_init(&fsi->allocated_ptys);
- fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
- fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
- fsi->sb = sb;
-
- return fsi;
-}
-
-static int
-devpts_fill_super(struct super_block *s, void *data, int silent)
+static int devpts_fill_super(struct super_block *s, struct fs_context *fc)
{
+ struct pts_fs_info *fsi = DEVPTS_SB(s);
struct inode *inode;
- int error;
s->s_iflags &= ~SB_I_NODEV;
s->s_blocksize = 1024;
@@ -435,20 +383,11 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
s->s_op = &devpts_sops;
s->s_d_op = &simple_dentry_operations;
s->s_time_gran = 1;
+ fsi->sb = s;
- error = -ENOMEM;
- s->s_fs_info = new_pts_fs_info(s);
- if (!s->s_fs_info)
- goto fail;
-
- error = parse_mount_options(data, PARSE_MOUNT, &DEVPTS_SB(s)->mount_opts);
- if (error)
- goto fail;
-
- error = -ENOMEM;
inode = new_inode(s);
if (!inode)
- goto fail;
+ return -ENOMEM;
inode->i_ino = 1;
simple_inode_init_ts(inode);
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
@@ -459,31 +398,60 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
s->s_root = d_make_root(inode);
if (!s->s_root) {
pr_err("get root dentry failed\n");
- goto fail;
+ return -ENOMEM;
}
- error = mknod_ptmx(s);
- if (error)
- goto fail_dput;
-
- return 0;
-fail_dput:
- dput(s->s_root);
- s->s_root = NULL;
-fail:
- return error;
+ return mknod_ptmx(s, fc);
}
/*
- * devpts_mount()
+ * devpts_get_tree()
*
* Mount a new (private) instance of devpts. PTYs created in this
* instance are independent of the PTYs in other devpts instances.
*/
-static struct dentry *devpts_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+static int devpts_get_tree(struct fs_context *fc)
+{
+ return get_tree_nodev(fc, devpts_fill_super);
+}
+
+static void devpts_free_fc(struct fs_context *fc)
+{
+ kfree(fc->s_fs_info);
+}
+
+static const struct fs_context_operations devpts_context_ops = {
+ .free = devpts_free_fc,
+ .parse_param = devpts_parse_param,
+ .get_tree = devpts_get_tree,
+ .reconfigure = devpts_reconfigure,
+};
+
+/*
+ * Set up the filesystem mount context.
+ */
+static int devpts_init_fs_context(struct fs_context *fc)
{
- return mount_nodev(fs_type, flags, data, devpts_fill_super);
+ struct pts_fs_info *fsi;
+
+ fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
+ if (!fsi)
+ return -ENOMEM;
+
+ ida_init(&fsi->allocated_ptys);
+ fsi->mount_opts.uid = GLOBAL_ROOT_UID;
+ fsi->mount_opts.gid = GLOBAL_ROOT_GID;
+ fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
+ fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
+ fsi->mount_opts.max = NR_UNIX98_PTY_MAX;
+
+ if (fc->purpose == FS_CONTEXT_FOR_MOUNT &&
+ current->nsproxy->mnt_ns == init_task.nsproxy->mnt_ns)
+ fsi->mount_opts.reserve = true;
+
+ fc->s_fs_info = fsi;
+ fc->ops = &devpts_context_ops;
+ return 0;
}
static void devpts_kill_sb(struct super_block *sb)
@@ -498,7 +466,8 @@ static void devpts_kill_sb(struct super_block *sb)
static struct file_system_type devpts_fs_type = {
.name = "devpts",
- .mount = devpts_mount,
+ .init_fs_context = devpts_init_fs_context,
+ .parameters = devpts_param_specs,
.kill_sb = devpts_kill_sb,
.fs_flags = FS_USERNS_MOUNT,
};
--
2.48.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] devtmpfs: replace ->mount with ->get_tree in public instance
2025-02-05 21:34 [PATCH 0/4] fs: last of the pseudofs mount api conversions Eric Sandeen
2025-02-05 21:34 ` [PATCH 1/4] pstore: convert to the new mount API Eric Sandeen
2025-02-05 21:34 ` [PATCH 2/4] vfs: Convert devpts to use " Eric Sandeen
@ 2025-02-05 21:34 ` Eric Sandeen
2025-02-05 21:34 ` [PATCH 4/4] vfs: remove some unused old mount api code Eric Sandeen
2025-02-06 11:04 ` [PATCH 0/4] fs: last of the pseudofs mount api conversions Christian Brauner
4 siblings, 0 replies; 10+ messages in thread
From: Eric Sandeen @ 2025-02-05 21:34 UTC (permalink / raw)
To: linux-fsdevel, brauner
Cc: viro, neilb, ebiederm, kees, tony.luck, Eric Sandeen
To finalize mount API conversion, remove the ->mount op from the public
instance in favor of ->get_tree etc. Copy most ops from the underlying
ops vector (whether it's shmem or ramfs) and substitute our own
->get_tree which simply takes an extra reference on the existing internal
mount as before.
Thanks to Al for the fs_context_for_reconfigure() idea.
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Neil Brown <neilb@suse.de>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
drivers/base/devtmpfs.c | 81 ++++++++++++++++++++++++++++++++---------
1 file changed, 64 insertions(+), 17 deletions(-)
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index b848764ef018..03a7c7902fcd 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -63,22 +63,6 @@ __setup("devtmpfs.mount=", mount_param);
static struct vfsmount *mnt;
-static struct dentry *public_dev_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data)
-{
- struct super_block *s = mnt->mnt_sb;
- int err;
-
- atomic_inc(&s->s_active);
- down_write(&s->s_umount);
- err = reconfigure_single(s, flags, data);
- if (err < 0) {
- deactivate_locked_super(s);
- return ERR_PTR(err);
- }
- return dget(s->s_root);
-}
-
static struct file_system_type internal_fs_type = {
.name = "devtmpfs",
#ifdef CONFIG_TMPFS
@@ -89,9 +73,40 @@ static struct file_system_type internal_fs_type = {
.kill_sb = kill_litter_super,
};
+/* Simply take a ref on the existing mount */
+static int devtmpfs_get_tree(struct fs_context *fc)
+{
+ struct super_block *sb = mnt->mnt_sb;
+
+ atomic_inc(&sb->s_active);
+ down_write(&sb->s_umount);
+ fc->root = dget(sb->s_root);
+ return 0;
+}
+
+/* Ops are filled in during init depending on underlying shmem or ramfs type */
+struct fs_context_operations devtmpfs_context_ops = {};
+
+/* Call the underlying initialization and set to our ops */
+static int devtmpfs_init_fs_context(struct fs_context *fc)
+{
+ int ret;
+#ifdef CONFIG_TMPFS
+ ret = shmem_init_fs_context(fc);
+#else
+ ret = ramfs_init_fs_context(fc);
+#endif
+ if (ret < 0)
+ return ret;
+
+ fc->ops = &devtmpfs_context_ops;
+
+ return 0;
+}
+
static struct file_system_type dev_fs_type = {
.name = "devtmpfs",
- .mount = public_dev_mount,
+ .init_fs_context = devtmpfs_init_fs_context,
};
static int devtmpfs_submit_req(struct req *req, const char *tmp)
@@ -442,6 +457,31 @@ static int __ref devtmpfsd(void *p)
return 0;
}
+/*
+ * Get the underlying (shmem/ramfs) context ops to build ours
+ */
+static int devtmpfs_configure_context(void)
+{
+ struct fs_context *fc;
+
+ fc = fs_context_for_reconfigure(mnt->mnt_root, mnt->mnt_sb->s_flags,
+ MS_RMT_MASK);
+ if (IS_ERR(fc))
+ return PTR_ERR(fc);
+
+ /* Set up devtmpfs_context_ops based on underlying type */
+ devtmpfs_context_ops.free = fc->ops->free;
+ devtmpfs_context_ops.dup = fc->ops->dup;
+ devtmpfs_context_ops.parse_param = fc->ops->parse_param;
+ devtmpfs_context_ops.parse_monolithic = fc->ops->parse_monolithic;
+ devtmpfs_context_ops.get_tree = &devtmpfs_get_tree;
+ devtmpfs_context_ops.reconfigure = fc->ops->reconfigure;
+
+ put_fs_context(fc);
+
+ return 0;
+}
+
/*
* Create devtmpfs instance, driver-core devices will add their device
* nodes here.
@@ -456,6 +496,13 @@ int __init devtmpfs_init(void)
pr_err("unable to create devtmpfs %ld\n", PTR_ERR(mnt));
return PTR_ERR(mnt);
}
+
+ err = devtmpfs_configure_context();
+ if (err) {
+ pr_err("unable to configure devtmpfs type %d\n", err);
+ return err;
+ }
+
err = register_filesystem(&dev_fs_type);
if (err) {
pr_err("unable to register devtmpfs type %d\n", err);
--
2.48.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] vfs: remove some unused old mount api code
2025-02-05 21:34 [PATCH 0/4] fs: last of the pseudofs mount api conversions Eric Sandeen
` (2 preceding siblings ...)
2025-02-05 21:34 ` [PATCH 3/4] devtmpfs: replace ->mount with ->get_tree in public instance Eric Sandeen
@ 2025-02-05 21:34 ` Eric Sandeen
2025-02-06 11:04 ` [PATCH 0/4] fs: last of the pseudofs mount api conversions Christian Brauner
4 siblings, 0 replies; 10+ messages in thread
From: Eric Sandeen @ 2025-02-05 21:34 UTC (permalink / raw)
To: linux-fsdevel, brauner
Cc: viro, neilb, ebiederm, kees, tony.luck, Eric Sandeen
Remove reconfigure_single, mount_single, and compare_single now
that no users remain.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
fs/super.c | 55 --------------------------------------
include/linux/fs.h | 3 ---
include/linux/fs_context.h | 2 --
3 files changed, 60 deletions(-)
diff --git a/fs/super.c b/fs/super.c
index 5a7db4a556e3..723176dee229 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1737,61 +1737,6 @@ struct dentry *mount_nodev(struct file_system_type *fs_type,
}
EXPORT_SYMBOL(mount_nodev);
-int reconfigure_single(struct super_block *s,
- int flags, void *data)
-{
- struct fs_context *fc;
- int ret;
-
- /* The caller really need to be passing fc down into mount_single(),
- * then a chunk of this can be removed. [Bollocks -- AV]
- * Better yet, reconfiguration shouldn't happen, but rather the second
- * mount should be rejected if the parameters are not compatible.
- */
- fc = fs_context_for_reconfigure(s->s_root, flags, MS_RMT_MASK);
- if (IS_ERR(fc))
- return PTR_ERR(fc);
-
- ret = parse_monolithic_mount_data(fc, data);
- if (ret < 0)
- goto out;
-
- ret = reconfigure_super(fc);
-out:
- put_fs_context(fc);
- return ret;
-}
-
-static int compare_single(struct super_block *s, void *p)
-{
- return 1;
-}
-
-struct dentry *mount_single(struct file_system_type *fs_type,
- int flags, void *data,
- int (*fill_super)(struct super_block *, void *, int))
-{
- struct super_block *s;
- int error;
-
- s = sget(fs_type, compare_single, set_anon_super, flags, NULL);
- if (IS_ERR(s))
- return ERR_CAST(s);
- if (!s->s_root) {
- error = fill_super(s, data, flags & SB_SILENT ? 1 : 0);
- if (!error)
- s->s_flags |= SB_ACTIVE;
- } else {
- error = reconfigure_single(s, flags, data);
- }
- if (unlikely(error)) {
- deactivate_locked_super(s);
- return ERR_PTR(error);
- }
- return dget(s->s_root);
-}
-EXPORT_SYMBOL(mount_single);
-
/**
* vfs_get_tree - Get the mountable root
* @fc: The superblock configuration context.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index be3ad155ec9f..ff5e8ab9f951 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2641,9 +2641,6 @@ static inline bool is_mgtime(const struct inode *inode)
extern struct dentry *mount_bdev(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int));
-extern struct dentry *mount_single(struct file_system_type *fs_type,
- int flags, void *data,
- int (*fill_super)(struct super_block *, void *, int));
extern struct dentry *mount_nodev(struct file_system_type *fs_type,
int flags, void *data,
int (*fill_super)(struct super_block *, void *, int));
diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
index 4b4bfef6f053..a19e4bd32e4d 100644
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -144,8 +144,6 @@ extern void put_fs_context(struct fs_context *fc);
extern int vfs_parse_fs_param_source(struct fs_context *fc,
struct fs_parameter *param);
extern void fc_drop_locked(struct fs_context *fc);
-int reconfigure_single(struct super_block *s,
- int flags, void *data);
extern int get_tree_nodev(struct fs_context *fc,
int (*fill_super)(struct super_block *sb,
--
2.48.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] pstore: convert to the new mount API
2025-02-05 21:34 ` [PATCH 1/4] pstore: convert to the new mount API Eric Sandeen
@ 2025-02-06 2:04 ` Kees Cook
2025-02-06 2:19 ` Eric Sandeen
0 siblings, 1 reply; 10+ messages in thread
From: Kees Cook @ 2025-02-06 2:04 UTC (permalink / raw)
To: Eric Sandeen, linux-fsdevel, brauner; +Cc: viro, neilb, ebiederm, tony.luck
On February 5, 2025 1:34:29 PM PST, Eric Sandeen <sandeen@redhat.com> wrote:
>Convert the pstore filesystem to the new mount API.
Thanks for doing this!
> [...]
>+static const struct fs_parameter_spec pstore_param_spec[] = {
>+ fsparam_u32 ("kmsg_bytes", Opt_kmsg_bytes),
>+ {}
I am reminded to change the global to u32 (ulong is way too big), and fix the pstore_set_kmsg_bytes() prototype to be u32 not int. :)
> [...]
>+ /* pstore has historically ignored invalid kmsg_bytes param */
>+ if (opt < 0)
>+ return 0;
Seems like a warning would be at least user-friendly. ;) I can add that later.
> [...]
>@@ -431,19 +434,33 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
> return -ENOMEM;
>
> scoped_guard(mutex, &pstore_sb_lock)
>- pstore_sb = sb;
>+ pstore_sb = sb;
Shouldn't scoped_guard() induce a indent?
>
> pstore_get_records(0);
>
> return 0;
> }
>
>-static struct dentry *pstore_mount(struct file_system_type *fs_type,
>- int flags, const char *dev_name, void *data)
>+static int pstore_get_tree(struct fs_context *fc)
>+{
>+ if (fc->root)
>+ return pstore_reconfigure(fc);
I need to double check that changing kmsg_size out from under an active pstore won't cause problems, but it's probably okay. (Honestly I've been wanting to deprecate it as a mount option -- it really should just be a module param, but that's a separate task.)
Reviewed-by: Kees Cook <kees@kernel.org>
(Is it easier to take this via fs or via pstore?)
-Kees
--
Kees Cook
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] pstore: convert to the new mount API
2025-02-06 2:04 ` Kees Cook
@ 2025-02-06 2:19 ` Eric Sandeen
2025-02-06 3:30 ` Kees Cook
2025-02-06 10:51 ` Christian Brauner
0 siblings, 2 replies; 10+ messages in thread
From: Eric Sandeen @ 2025-02-06 2:19 UTC (permalink / raw)
To: Kees Cook, linux-fsdevel, brauner; +Cc: viro, neilb, ebiederm, tony.luck
On 2/5/25 8:04 PM, Kees Cook wrote:
>> @@ -431,19 +434,33 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
>> return -ENOMEM;
>>
>> scoped_guard(mutex, &pstore_sb_lock)
>> - pstore_sb = sb;
>> + pstore_sb = sb;
> Shouldn't scoped_guard() induce a indent?
Whoops, not sure how that happened, sorry.
Fix on commit or send V2?
>> pstore_get_records(0);
>>
>> return 0;
>> }
>>
>> -static struct dentry *pstore_mount(struct file_system_type *fs_type,
>> - int flags, const char *dev_name, void *data)
>> +static int pstore_get_tree(struct fs_context *fc)
>> +{
>> + if (fc->root)
>> + return pstore_reconfigure(fc);
> I need to double check that changing kmsg_size out from under an active pstore won't cause problems, but it's probably okay. (Honestly I've been wanting to deprecate it as a mount option -- it really should just be a module param, but that's a separate task.)
Honestly I struggled with this for a while, not quite sure what's right.
> Reviewed-by: Kees Cook <kees@kernel.org>
Thanks,
-Eric
> (Is it easier to take this via fs or via pstore?)
>
> -Kees
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] pstore: convert to the new mount API
2025-02-06 2:19 ` Eric Sandeen
@ 2025-02-06 3:30 ` Kees Cook
2025-02-06 10:51 ` Christian Brauner
1 sibling, 0 replies; 10+ messages in thread
From: Kees Cook @ 2025-02-06 3:30 UTC (permalink / raw)
To: Eric Sandeen, linux-fsdevel, brauner; +Cc: viro, neilb, ebiederm, tony.luck
On February 5, 2025 6:19:06 PM PST, Eric Sandeen <sandeen@redhat.com> wrote:
>On 2/5/25 8:04 PM, Kees Cook wrote:
>>> @@ -431,19 +434,33 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
>>> return -ENOMEM;
>>>
>>> scoped_guard(mutex, &pstore_sb_lock)
>>> - pstore_sb = sb;
>>> + pstore_sb = sb;
>> Shouldn't scoped_guard() induce a indent?
>
>Whoops, not sure how that happened, sorry.
>
>Fix on commit or send V2?
If I should carry it in pstore, a v2 is appreciated. If you're taking it via fs, fix on commit is fine by me. :)
>
>>> pstore_get_records(0);
>>>
>>> return 0;
>>> }
>>>
>>> -static struct dentry *pstore_mount(struct file_system_type *fs_type,
>>> - int flags, const char *dev_name, void *data)
>>> +static int pstore_get_tree(struct fs_context *fc)
>>> +{
>>> + if (fc->root)
>>> + return pstore_reconfigure(fc);
>
>> I need to double check that changing kmsg_size out from under an active pstore won't cause problems, but it's probably okay. (Honestly I've been wanting to deprecate it as a mount option -- it really should just be a module param, but that's a separate task.)
>
>Honestly I struggled with this for a while, not quite sure what's right.
I found the place I need to fix, but it's an existing problem and won't conflict. I'll get it fixed.
-Kees
>
>> Reviewed-by: Kees Cook <kees@kernel.org>
>
>Thanks,
>-Eric
>
>> (Is it easier to take this via fs or via pstore?)
>>
>> -Kees
>
--
Kees Cook
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] pstore: convert to the new mount API
2025-02-06 2:19 ` Eric Sandeen
2025-02-06 3:30 ` Kees Cook
@ 2025-02-06 10:51 ` Christian Brauner
1 sibling, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2025-02-06 10:51 UTC (permalink / raw)
To: Eric Sandeen; +Cc: Kees Cook, linux-fsdevel, viro, neilb, ebiederm, tony.luck
On Wed, Feb 05, 2025 at 08:19:06PM -0600, Eric Sandeen wrote:
> On 2/5/25 8:04 PM, Kees Cook wrote:
> >> @@ -431,19 +434,33 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
> >> return -ENOMEM;
> >>
> >> scoped_guard(mutex, &pstore_sb_lock)
> >> - pstore_sb = sb;
> >> + pstore_sb = sb;
> > Shouldn't scoped_guard() induce a indent?
>
> Whoops, not sure how that happened, sorry.
>
> Fix on commit or send V2?
I fixed it.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/4] fs: last of the pseudofs mount api conversions
2025-02-05 21:34 [PATCH 0/4] fs: last of the pseudofs mount api conversions Eric Sandeen
` (3 preceding siblings ...)
2025-02-05 21:34 ` [PATCH 4/4] vfs: remove some unused old mount api code Eric Sandeen
@ 2025-02-06 11:04 ` Christian Brauner
4 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2025-02-06 11:04 UTC (permalink / raw)
To: Eric Sandeen
Cc: Christian Brauner, viro, neilb, ebiederm, kees, tony.luck,
linux-fsdevel
On Wed, 05 Feb 2025 15:34:28 -0600, Eric Sandeen wrote:
> Notes:
>
> pstore used mount_single, which used to transparently do a
> remount operation on a fresh mount of an existing superblock.
> The new get_tree_single does not do this, but prior discussion
> on fsdevel seems to indicate that this isn't expected to be a
> problem. We can watch for issues.
>
> [...]
Looks good to me. Thanks for enabling us to get rid of a bunch of code.
---
Applied to the vfs-6.15.mount.api branch of the vfs/vfs.git tree.
Patches in the vfs-6.15.mount.api 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-6.15.mount.api
[1/4] pstore: convert to the new mount API
https://git.kernel.org/vfs/vfs/c/f584714cffb9
[2/4] vfs: Convert devpts to use the new mount API
https://git.kernel.org/vfs/vfs/c/cc0876f817d6
[3/4] devtmpfs: replace ->mount with ->get_tree in public instance
https://git.kernel.org/vfs/vfs/c/cb0e0a8bf4e1
[4/4] vfs: remove some unused old mount api code
https://git.kernel.org/vfs/vfs/c/bdfa77e7c6bf
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-02-06 11:05 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-05 21:34 [PATCH 0/4] fs: last of the pseudofs mount api conversions Eric Sandeen
2025-02-05 21:34 ` [PATCH 1/4] pstore: convert to the new mount API Eric Sandeen
2025-02-06 2:04 ` Kees Cook
2025-02-06 2:19 ` Eric Sandeen
2025-02-06 3:30 ` Kees Cook
2025-02-06 10:51 ` Christian Brauner
2025-02-05 21:34 ` [PATCH 2/4] vfs: Convert devpts to use " Eric Sandeen
2025-02-05 21:34 ` [PATCH 3/4] devtmpfs: replace ->mount with ->get_tree in public instance Eric Sandeen
2025-02-05 21:34 ` [PATCH 4/4] vfs: remove some unused old mount api code Eric Sandeen
2025-02-06 11:04 ` [PATCH 0/4] fs: last of the pseudofs mount api conversions Christian Brauner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox