From d401727ea0d7a48eaa01a8089f6b91a8121dcaac Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Jun 2019 18:43:09 -0400 Subject: devtmpfs: don't mix {ramfs,shmem}_fill_super() with mount_single() Create an internal-only type matching the current devtmpfs, never register it and have one kernel-internal mount done. That thing gets mounted only once, so it is free to use mount_nodev(). The "public" devtmpfs (the one we do register, and only after the internal mount of the real thing is done) simply gets and returns an extra reference to the internal superblock. Signed-off-by: Al Viro --- drivers/base/devtmpfs.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'drivers/base/devtmpfs.c') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index ba5c80903efe..bafdf86b0497 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -56,22 +56,38 @@ static int __init mount_param(char *str) } __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; + atomic_inc(&s->s_active); + down_write(&s->s_umount); + return dget(s->s_root); +} + static struct dentry *dev_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { #ifdef CONFIG_TMPFS - return mount_single(fs_type, flags, data, shmem_fill_super); + return mount_nodev(fs_type, flags, data, shmem_fill_super); #else - return mount_single(fs_type, flags, data, ramfs_fill_super); + return ramfs_mount(fs_type, flags, dev_name, data); #endif } -static struct file_system_type dev_fs_type = { +static struct file_system_type internal_fs_type = { .name = "devtmpfs", .mount = dev_mount, .kill_sb = kill_litter_super, }; +static struct file_system_type dev_fs_type = { + .name = "devtmpfs", + .mount = public_dev_mount, +}; + #ifdef CONFIG_BLOCK static inline int is_blockdev(struct device *dev) { @@ -378,12 +394,11 @@ static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, static int devtmpfsd(void *p) { - char options[] = "mode=0755"; int *err = p; *err = ksys_unshare(CLONE_NEWNS); if (*err) goto out; - *err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options); + *err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL); if (*err) goto out; ksys_chdir("/.."); /* will traverse into overmounted root */ @@ -420,7 +435,16 @@ out: */ int __init devtmpfs_init(void) { - int err = register_filesystem(&dev_fs_type); + char opts[] = "mode=0755"; + int err; + + mnt = vfs_kern_mount(&internal_fs_type, 0, "devtmpfs", opts); + if (IS_ERR(mnt)) { + printk(KERN_ERR "devtmpfs: unable to create devtmpfs %ld\n", + PTR_ERR(mnt)); + return PTR_ERR(mnt); + } + err = register_filesystem(&dev_fs_type); if (err) { printk(KERN_ERR "devtmpfs: unable to register devtmpfs " "type %i\n", err); -- cgit v1.2.2 From 7e30d2a5eb0b2d5853f06cb8a2d44937d80a6bd6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Jun 2019 18:56:53 -0400 Subject: make shmem_fill_super() static ... have callers use shmem_mount() Signed-off-by: Al Viro --- drivers/base/devtmpfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base/devtmpfs.c') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index bafdf86b0497..dabf5006a254 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -71,7 +71,7 @@ static struct dentry *dev_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { #ifdef CONFIG_TMPFS - return mount_nodev(fs_type, flags, data, shmem_fill_super); + return shmem_mount(fs_type, flags, dev_name, data); #else return ramfs_mount(fs_type, flags, dev_name, data); #endif -- cgit v1.2.2 From f32356261d44d580649a7abce1156d15d49cf20f Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:31 +0000 Subject: vfs: Convert ramfs, shmem, tmpfs, devtmpfs, rootfs to use the new mount API Convert the ramfs, shmem, tmpfs, devtmpfs and rootfs filesystems 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. Note that tmpfs is slightly tricky as it can contain embedded commas, so it can't be trivially split up using strsep() to break on commas in generic_parse_monolithic(). Instead, tmpfs has to supply its own generic parser. However, if tmpfs changes, then devtmpfs and rootfs, which are wrappers around tmpfs or ramfs, must change too - and thus so must ramfs, so these had to be converted also. [AV: rewritten] Signed-off-by: David Howells cc: Hugh Dickins cc: linux-mm@kvack.org Signed-off-by: Al Viro --- drivers/base/devtmpfs.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/base/devtmpfs.c') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index dabf5006a254..30d0523014e0 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -67,19 +67,15 @@ static struct dentry *public_dev_mount(struct file_system_type *fs_type, int fla return dget(s->s_root); } -static struct dentry *dev_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ +static struct file_system_type internal_fs_type = { + .name = "devtmpfs", #ifdef CONFIG_TMPFS - return shmem_mount(fs_type, flags, dev_name, data); + .init_fs_context = shmem_init_fs_context, + .parameters = &shmem_fs_parameters, #else - return ramfs_mount(fs_type, flags, dev_name, data); + .init_fs_context = ramfs_init_fs_context, + .parameters = &ramfs_fs_parameters, #endif -} - -static struct file_system_type internal_fs_type = { - .name = "devtmpfs", - .mount = dev_mount, .kill_sb = kill_litter_super, }; -- cgit v1.2.2