From 7e5f7bb08b8cefd3a7e8961861f47fe1f0e830d4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:57 +0100 Subject: unexport simple_dname() Signed-off-by: Al Viro --- fs/d_path.c | 1 - fs/internal.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/d_path.c b/fs/d_path.c index e8fce6b1174f..a7d0a96b35ce 100644 --- a/fs/d_path.c +++ b/fs/d_path.c @@ -316,7 +316,6 @@ char *simple_dname(struct dentry *dentry, char *buffer, int buflen) end = ERR_PTR(-ENAMETOOLONG); return end; } -EXPORT_SYMBOL(simple_dname); /* * Write full pathname from the root of the filesystem into the buffer. diff --git a/fs/internal.h b/fs/internal.h index 0010889f2e85..1ac2b8f6c621 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -160,6 +160,7 @@ extern int d_set_mounted(struct dentry *dentry); extern long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc); extern struct dentry *d_alloc_cursor(struct dentry *); extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *); +extern char *simple_dname(struct dentry *, char *, int); /* * read_write.c -- cgit v1.2.3 From 1f58bb18f6f28d1df0b7144d90bc90ee5672416d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:57 +0100 Subject: mount_pseudo(): drop 'name' argument, switch to d_make_root() Once upon a time we used to set ->d_name of e.g. pipefs root so that d_path() on pipes would work. These days it's completely pointless - dentries of pipes are not even connected to pipefs root. However, mount_pseudo() had set the root dentry name (passed as the second argument) and callers kept inventing names to pass to it. Including those that didn't *have* any non-root dentries to start with... All of that had been pointless for about 8 years now; it's time to get rid of that cargo-culting... Signed-off-by: Al Viro --- arch/ia64/kernel/perfmon.c | 2 +- drivers/dax/super.c | 2 +- drivers/gpu/drm/drm_drv.c | 6 +----- drivers/misc/cxl/api.c | 3 +-- drivers/scsi/cxlflash/ocxl_hw.c | 3 +-- drivers/virtio/virtio_balloon.c | 3 +-- fs/aio.c | 3 +-- fs/anon_inodes.c | 4 ++-- fs/block_dev.c | 2 +- fs/btrfs/tests/btrfs-tests.c | 2 +- fs/libfs.c | 12 +++--------- fs/nsfs.c | 2 +- fs/pipe.c | 2 +- include/linux/fs.h | 6 +++--- mm/z3fold.c | 2 +- mm/zsmalloc.c | 2 +- net/socket.c | 2 +- 17 files changed, 22 insertions(+), 36 deletions(-) (limited to 'fs') diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 7a969f4c3534..a30da6f2c28e 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -602,7 +602,7 @@ static const struct dentry_operations pfmfs_dentry_operations; static struct dentry * pfmfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "pfm:", NULL, &pfmfs_dentry_operations, + return mount_pseudo(fs_type, NULL, &pfmfs_dentry_operations, PFMFS_MAGIC); } diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 35f051efaf35..f83814eea5ad 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -440,7 +440,7 @@ static const struct super_operations dax_sops = { static struct dentry *dax_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "dax:", &dax_sops, NULL, DAXFS_MAGIC); + return mount_pseudo(fs_type, &dax_sops, NULL, DAXFS_MAGIC); } static struct file_system_type dax_fs_type = { diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8b44ac9a92ae..48365c62a190 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -535,11 +535,7 @@ static struct vfsmount *drm_fs_mnt; static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, - "drm:", - NULL, - NULL, - 0x010203ff); + return mount_pseudo(fs_type, NULL, NULL, 0x010203ff); } static struct file_system_type drm_fs_type = { diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index a59c7af79873..1f2b0535a8cf 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -40,8 +40,7 @@ static struct vfsmount *cxl_vfs_mount; static struct dentry *cxl_fs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "cxl:", NULL, NULL, - CXL_PSEUDO_FS_MAGIC); + return mount_pseudo(fs_type, NULL, NULL, CXL_PSEUDO_FS_MAGIC); } static struct file_system_type cxl_fs_type = { diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c index 31cfdf2c8c30..38e1fbd2b406 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.c +++ b/drivers/scsi/cxlflash/ocxl_hw.c @@ -48,8 +48,7 @@ static struct dentry *ocxlflash_fs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "ocxlflash:", NULL, NULL, - OCXLFLASH_FS_MAGIC); + return mount_pseudo(fs_type, NULL, NULL, OCXLFLASH_FS_MAGIC); } static struct file_system_type ocxlflash_fs_type = { diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 554d1a98d193..62bafc4f2662 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -761,8 +761,7 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, static struct dentry *balloon_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "balloon-kvm:", NULL, NULL, - BALLOON_KVM_MAGIC); + return mount_pseudo(fs_type, NULL, NULL, BALLOON_KVM_MAGIC); } static struct file_system_type balloon_fs = { diff --git a/fs/aio.c b/fs/aio.c index 3490d1fa0e16..09bc35fa6810 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -252,8 +252,7 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) static struct dentry *aio_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, NULL, - AIO_RING_MAGIC); + struct dentry *root = mount_pseudo(fs_type, NULL, NULL, AIO_RING_MAGIC); if (!IS_ERR(root)) root->d_sb->s_iflags |= SB_I_NOEXEC; diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 91262c34b797..644d0837aafe 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -41,8 +41,8 @@ static const struct dentry_operations anon_inodefs_dentry_operations = { static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "anon_inode:", NULL, - &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC); + return mount_pseudo(fs_type, NULL, &anon_inodefs_dentry_operations, + ANON_INODE_FS_MAGIC); } static struct file_system_type anon_inode_fs_type = { diff --git a/fs/block_dev.c b/fs/block_dev.c index 0f7552a87d54..3143da7b0998 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -837,7 +837,7 @@ static struct dentry *bd_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { struct dentry *dent; - dent = mount_pseudo(fs_type, "bdev:", &bdev_sops, NULL, BDEVFS_MAGIC); + dent = mount_pseudo(fs_type, &bdev_sops, NULL, BDEVFS_MAGIC); if (!IS_ERR(dent)) dent->d_sb->s_iflags |= SB_I_CGROUPWB; return dent; diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c index 9238fd4f1734..6da54323eaf8 100644 --- a/fs/btrfs/tests/btrfs-tests.c +++ b/fs/btrfs/tests/btrfs-tests.c @@ -36,7 +36,7 @@ static struct dentry *btrfs_test_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "btrfs_test:", &btrfs_test_super_ops, + return mount_pseudo(fs_type, &btrfs_test_super_ops, NULL, BTRFS_TEST_MAGIC); } diff --git a/fs/libfs.c b/fs/libfs.c index 4b59b1816efb..030e545f586e 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -239,14 +239,12 @@ static const struct super_operations simple_super_operations = { * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that * will never be mountable) */ -struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name, +struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, const struct super_operations *ops, const struct xattr_handler **xattr, const struct dentry_operations *dops, unsigned long magic) { struct super_block *s; - struct dentry *dentry; struct inode *root; - struct qstr d_name = QSTR_INIT(name, strlen(name)); s = sget_userns(fs_type, NULL, set_anon_super, SB_KERNMOUNT|SB_NOUSER, &init_user_ns, NULL); @@ -271,13 +269,9 @@ struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name, root->i_ino = 1; root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_atime = root->i_mtime = root->i_ctime = current_time(root); - dentry = __d_alloc(s, &d_name); - if (!dentry) { - iput(root); + s->s_root = d_make_root(root); + if (!s->s_root) goto Enomem; - } - d_instantiate(dentry, root); - s->s_root = dentry; s->s_d_op = dops; s->s_flags |= SB_ACTIVE; return dget(s->s_root); diff --git a/fs/nsfs.c b/fs/nsfs.c index e3bf08c5af41..b3c49ddc0f85 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -261,7 +261,7 @@ static const struct super_operations nsfs_ops = { static struct dentry *nsfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "nsfs:", &nsfs_ops, + return mount_pseudo(fs_type, &nsfs_ops, &ns_dentry_operations, NSFS_MAGIC); } static struct file_system_type nsfs = { diff --git a/fs/pipe.c b/fs/pipe.c index 41065901106b..99a023730e6f 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1185,7 +1185,7 @@ static const struct super_operations pipefs_ops = { static struct dentry *pipefs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "pipe:", &pipefs_ops, + return mount_pseudo(fs_type, &pipefs_ops, &pipefs_dentry_operations, PIPEFS_MAGIC); } diff --git a/include/linux/fs.h b/include/linux/fs.h index f7fdfe93e25d..b06251dd429f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2257,18 +2257,18 @@ struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), int flags, void *data); -extern struct dentry *mount_pseudo_xattr(struct file_system_type *, char *, +extern struct dentry *mount_pseudo_xattr(struct file_system_type *, const struct super_operations *ops, const struct xattr_handler **xattr, const struct dentry_operations *dops, unsigned long); static inline struct dentry * -mount_pseudo(struct file_system_type *fs_type, char *name, +mount_pseudo(struct file_system_type *fs_type, const struct super_operations *ops, const struct dentry_operations *dops, unsigned long magic) { - return mount_pseudo_xattr(fs_type, name, ops, NULL, dops, magic); + return mount_pseudo_xattr(fs_type, ops, NULL, dops, magic); } /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ diff --git a/mm/z3fold.c b/mm/z3fold.c index 0b14daf930a8..abeb5bcbea57 100644 --- a/mm/z3fold.c +++ b/mm/z3fold.c @@ -242,7 +242,7 @@ static inline void free_handle(unsigned long handle) static struct dentry *z3fold_do_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "z3fold:", NULL, NULL, 0x33); + return mount_pseudo(fs_type, NULL, NULL, 0x33); } static struct file_system_type z3fold_fs = { diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index d9f831f63625..ef230be8c03e 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -1817,7 +1817,7 @@ static void lock_zspage(struct zspage *zspage) static struct dentry *zs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "zsmalloc:", NULL, NULL, ZSMALLOC_MAGIC); + return mount_pseudo(fs_type, NULL, NULL, ZSMALLOC_MAGIC); } static struct file_system_type zsmalloc_fs = { diff --git a/net/socket.c b/net/socket.c index 472fbefa5d9b..c86679584eed 100644 --- a/net/socket.c +++ b/net/socket.c @@ -362,7 +362,7 @@ static const struct xattr_handler *sockfs_xattr_handlers[] = { static struct dentry *sockfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops, + return mount_pseudo_xattr(fs_type, &sockfs_ops, sockfs_xattr_handlers, &sockfs_dentry_operations, SOCKFS_MAGIC); } -- cgit v1.2.3 From f7a9945184100b531f0de3b12c617a349236dd8a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 12:42:58 -0400 Subject: no need to protect against put_user_ns(NULL) it's a no-op Signed-off-by: Al Viro --- arch/x86/kernel/cpu/resctrl/rdtgroup.c | 3 +-- fs/sysfs/mount.c | 3 +-- kernel/cgroup/cgroup.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c index 333c177a2471..68bd609026e6 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -2108,8 +2108,7 @@ static int rdt_init_fs_context(struct fs_context *fc) ctx->kfc.magic = RDTGROUP_SUPER_MAGIC; fc->fs_private = &ctx->kfc; fc->ops = &rdt_fs_context_ops; - if (fc->user_ns) - put_user_ns(fc->user_ns); + put_user_ns(fc->user_ns); fc->user_ns = get_user_ns(&init_user_ns); fc->global = true; return 0; diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 1b56686ab178..db81cfbab9d6 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -72,8 +72,7 @@ static int sysfs_init_fs_context(struct fs_context *fc) fc->fs_private = kfc; fc->ops = &sysfs_fs_context_ops; if (netns) { - if (fc->user_ns) - put_user_ns(fc->user_ns); + put_user_ns(fc->user_ns); fc->user_ns = get_user_ns(netns->user_ns); } fc->global = true; diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 217cec4e22c6..bbcdd3457eb0 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -2184,8 +2184,7 @@ static int cgroup_init_fs_context(struct fs_context *fc) fc->ops = &cgroup_fs_context_ops; else fc->ops = &cgroup1_fs_context_ops; - if (fc->user_ns) - put_user_ns(fc->user_ns); + put_user_ns(fc->user_ns); fc->user_ns = get_user_ns(ctx->ns->user_ns); fc->global = true; return 0; -- cgit v1.2.3 From feb8ae43a7b33148028829b1b1691b28c874c952 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 13:18:42 -0400 Subject: start massaging the checks in sget_...(): move to sget_userns() there are 3 remaining callers of sget_userns() - sget(), mount_ns() and mount_pseudo_xattr(). Extra check in sget() is conditional upon mount being neither KERNMOUNT nor SUBMOUNT, the identical one in mount_ns() - upon being not KERNMOUNT; mount_pseudo_xattr() has no such checks at all. However, mount_ns() is never used with SUBMOUNT and mount_pseudo_xattr() is used only for KERNMOUNT, so both would be fine with the same logics as currently done in sget(), allowing to consolidate the entire thing in sget_userns() itself. That's not where these checks will end up in the long run, though - the whole reason why they'd been done so deep in the bowels of mount(2) was that there had been no way for a filesystem to specify which userns to look at until it has entered ->mount(). Now there is a place where filesystem could override the defaults - ->init_fs_context(). Which allows to pull the checks out into the callers of vfs_get_tree(). That'll take quite a bit of massage, but that mess is possible to tease apart. Signed-off-by: Al Viro --- fs/super.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/super.c b/fs/super.c index 2739f57515f8..9c371a04e1b6 100644 --- a/fs/super.c +++ b/fs/super.c @@ -583,6 +583,10 @@ struct super_block *sget_userns(struct file_system_type *type, struct super_block *old; int err; + /* Ensure the requestor has permissions over the target filesystem */ + if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !ns_capable(user_ns, CAP_SYS_ADMIN)) + return ERR_PTR(-EPERM); + if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !(type->fs_flags & FS_USERNS_MOUNT) && !capable(CAP_SYS_ADMIN)) @@ -653,10 +657,6 @@ struct super_block *sget(struct file_system_type *type, if (flags & SB_SUBMOUNT) user_ns = &init_user_ns; - /* Ensure the requestor has permissions over the target filesystem */ - if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !ns_capable(user_ns, CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - return sget_userns(type, test, set, flags, user_ns, data); } @@ -1164,12 +1164,6 @@ struct dentry *mount_ns(struct file_system_type *fs_type, { struct super_block *sb; - /* Don't allow mounting unless the caller has CAP_SYS_ADMIN - * over the namespace. - */ - if (!(flags & SB_KERNMOUNT) && !ns_capable(user_ns, CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - sb = sget_userns(fs_type, ns_test_super, ns_set_super, flags, user_ns, ns); if (IS_ERR(sb)) -- cgit v1.2.3 From 0ce0cf12fc4c6a089717ff613d76457052cf4303 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 15:42:48 -0400 Subject: consolidate the capability checks in sget_{fc,userns}() ... into a common helper - mount_capable(type, userns) Signed-off-by: Al Viro --- fs/super.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'fs') diff --git a/fs/super.c b/fs/super.c index 9c371a04e1b6..3ba91d70c2a8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -476,6 +476,14 @@ void generic_shutdown_super(struct super_block *sb) EXPORT_SYMBOL(generic_shutdown_super); +bool mount_capable(struct file_system_type *type, struct user_namespace *userns) +{ + if (!(type->fs_flags & FS_USERNS_MOUNT)) + return capable(CAP_SYS_ADMIN); + else + return ns_capable(userns, CAP_SYS_ADMIN); +} + /** * sget_fc - Find or create a superblock * @fc: Filesystem context. @@ -505,16 +513,8 @@ struct super_block *sget_fc(struct fs_context *fc, if (!(fc->sb_flags & SB_KERNMOUNT) && fc->purpose != FS_CONTEXT_FOR_SUBMOUNT) { - /* Don't allow mounting unless the caller has CAP_SYS_ADMIN - * over the namespace. - */ - if (!(fc->fs_type->fs_flags & FS_USERNS_MOUNT)) { - if (!capable(CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - } else { - if (!ns_capable(fc->user_ns, CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - } + if (!mount_capable(fc->fs_type, user_ns)) + return ERR_PTR(-EPERM); } retry: @@ -583,14 +583,10 @@ struct super_block *sget_userns(struct file_system_type *type, struct super_block *old; int err; - /* Ensure the requestor has permissions over the target filesystem */ - if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !ns_capable(user_ns, CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - - if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && - !(type->fs_flags & FS_USERNS_MOUNT) && - !capable(CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); + if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT))) { + if (!mount_capable(type, user_ns)) + return ERR_PTR(-EPERM); + } retry: spin_lock(&sb_lock); if (test) { -- cgit v1.2.3 From 96a374a35f822e53cad3b011dd5fbadec1b1473f Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:27 +0000 Subject: vfs: Convert nfsctl to use the new mount API Convert the nfsctl 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 cc: "J. Bruce Fields" cc: Jeff Layton cc: linux-nfs@vger.kernel.org --- fs/nfsd/nfsctl.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 90972e1fd785..0f154b0e1c8a 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -1146,7 +1147,7 @@ static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size) * populating the filesystem. */ -static int nfsd_fill_super(struct super_block * sb, void * data, int silent) +static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc) { static const struct tree_descr nfsd_files[] = { [NFSD_List] = {"exports", &exports_nfsd_operations, S_IRUGO}, @@ -1176,15 +1177,33 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) #endif /* last one */ {""} }; - get_net(sb->s_fs_info); + return simple_fill_super(sb, 0x6e667364, nfsd_files); } -static struct dentry *nfsd_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int nfsd_fs_get_tree(struct fs_context *fc) +{ + fc->s_fs_info = get_net(fc->net_ns); + return vfs_get_super(fc, vfs_get_keyed_super, nfsd_fill_super); +} + +static void nfsd_fs_free_fc(struct fs_context *fc) +{ + if (fc->s_fs_info) + put_net(fc->s_fs_info); +} + +static const struct fs_context_operations nfsd_fs_context_ops = { + .free = nfsd_fs_free_fc, + .get_tree = nfsd_fs_get_tree, +}; + +static int nfsd_init_fs_context(struct fs_context *fc) { - struct net *net = current->nsproxy->net_ns; - return mount_ns(fs_type, flags, data, net, net->user_ns, nfsd_fill_super); + put_user_ns(fc->user_ns); + fc->user_ns = get_user_ns(fc->net_ns->user_ns); + fc->ops = &nfsd_fs_context_ops; + return 0; } static void nfsd_umount(struct super_block *sb) @@ -1198,7 +1217,7 @@ static void nfsd_umount(struct super_block *sb) static struct file_system_type nfsd_fs_type = { .owner = THIS_MODULE, .name = "nfsd", - .mount = nfsd_mount, + .init_fs_context = nfsd_init_fs_context, .kill_sb = nfsd_umount, }; MODULE_ALIAS_FS("nfsd"); -- cgit v1.2.3 From bb7b6b2bbdb827e68cd506c8f5e3ba13215cccb2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:28 +0000 Subject: vfs: Kill mount_ns() Kill mount_ns() as it has been replaced by vfs_get_super() in the new mount API. Signed-off-by: David Howells cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/super.c | 38 -------------------------------------- include/linux/fs.h | 3 --- 2 files changed, 41 deletions(-) (limited to 'fs') diff --git a/fs/super.c b/fs/super.c index 3ba91d70c2a8..6919f5c728f0 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1143,44 +1143,6 @@ void kill_litter_super(struct super_block *sb) } EXPORT_SYMBOL(kill_litter_super); -static int ns_test_super(struct super_block *sb, void *data) -{ - return sb->s_fs_info == data; -} - -static int ns_set_super(struct super_block *sb, void *data) -{ - sb->s_fs_info = data; - return set_anon_super(sb, NULL); -} - -struct dentry *mount_ns(struct file_system_type *fs_type, - int flags, void *data, void *ns, struct user_namespace *user_ns, - int (*fill_super)(struct super_block *, void *, int)) -{ - struct super_block *sb; - - sb = sget_userns(fs_type, ns_test_super, ns_set_super, flags, - user_ns, ns); - if (IS_ERR(sb)) - return ERR_CAST(sb); - - if (!sb->s_root) { - int err; - err = fill_super(sb, data, flags & SB_SILENT ? 1 : 0); - if (err) { - deactivate_locked_super(sb); - return ERR_PTR(err); - } - - sb->s_flags |= SB_ACTIVE; - } - - return dget(sb->s_root); -} - -EXPORT_SYMBOL(mount_ns); - int set_anon_super_fc(struct super_block *sb, struct fs_context *fc) { return set_anon_super(sb, NULL); diff --git a/include/linux/fs.h b/include/linux/fs.h index b06251dd429f..790342cf4df9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2206,9 +2206,6 @@ struct file_system_type { #define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME) -extern struct dentry *mount_ns(struct file_system_type *fs_type, - int flags, void *data, void *ns, struct user_namespace *user_ns, - int (*fill_super)(struct super_block *, void *, int)); #ifdef CONFIG_BLOCK extern struct dentry *mount_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, -- cgit v1.2.3 From 2527b284defaeadf74829b0b0bd3207ca7f165eb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 17:09:01 -0400 Subject: move the capability checks from sget_userns() to legacy_get_tree() 1) all call chains leading to sget_userns() pass through ->mount() instances. 2) none of ->mount() instances is ever called directly - the only call site is legacy_get_tree() 3) all remaining ->mount() instances end up calling sget_userns() IOW, we might as well do the capability checks just before calling ->mount(). As for the arguments passed to mount_capable(), in case of call chains to sget_userns() going through sget(), we either don't call mount_capable() at all, or pass current_user_ns() to it. The call chains going through mount_pseudo_xattr() don't call mount_capable() at all (SB_KERNMOUNT in flags on those). That could've been split into smaller steps (lifting the checks into sget(), then callers of sget(), then all the way to the entries of every ->mount() out there, then to the sole caller), but that would be too much churn for little benefit... Signed-off-by: Al Viro --- fs/fs_context.c | 5 +++++ fs/internal.h | 2 ++ fs/super.c | 4 ---- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/fs_context.c b/fs/fs_context.c index a47ccd5a4a78..746a5871959c 100644 --- a/fs/fs_context.c +++ b/fs/fs_context.c @@ -662,6 +662,11 @@ static int legacy_get_tree(struct fs_context *fc) struct super_block *sb; struct dentry *root; + if (!(fc->sb_flags & (SB_KERNMOUNT|SB_SUBMOUNT))) { + if (!mount_capable(fc->fs_type, current_user_ns())) + return -EPERM; + } + root = fc->fs_type->mount(fc->fs_type, fc->sb_flags, fc->source, ctx->legacy_data); if (IS_ERR(root)) diff --git a/fs/internal.h b/fs/internal.h index 1ac2b8f6c621..65db901420af 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -18,6 +18,7 @@ struct path; struct mount; struct shrink_control; struct fs_context; +struct user_namespace; /* * block_dev.c @@ -113,6 +114,7 @@ extern struct file *alloc_empty_file_noaccount(int, const struct cred *); extern int reconfigure_super(struct fs_context *); extern bool trylock_super(struct super_block *sb); extern struct super_block *user_get_super(dev_t); +extern bool mount_capable(struct file_system_type *, struct user_namespace *); /* * open.c diff --git a/fs/super.c b/fs/super.c index 6919f5c728f0..bdb03255c7ea 100644 --- a/fs/super.c +++ b/fs/super.c @@ -583,10 +583,6 @@ struct super_block *sget_userns(struct file_system_type *type, struct super_block *old; int err; - if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT))) { - if (!mount_capable(type, user_ns)) - return ERR_PTR(-EPERM); - } retry: spin_lock(&sb_lock); if (test) { -- cgit v1.2.3 From fd912087f4a897cfdf8274f8085c501742638be2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 17:23:30 -0400 Subject: legacy_get_tree(): pass fc->user_ns to mount_capable() guaranteed to be equal to current_user_ns() here - it has not been changed since alloc_fs_context() (nothing in legacy methods changes it) and since we don't have SB_SUBMOUNT, that must've been FS_CONTEXT_FOR_MOUNT. And in that case we have fc->user_ns set to fc->cred->user_ns, i.e. current_cred()->user_ns, i.e. current_user_ns() Signed-off-by: Al Viro --- fs/fs_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/fs_context.c b/fs/fs_context.c index 746a5871959c..d75ba0eb8c5b 100644 --- a/fs/fs_context.c +++ b/fs/fs_context.c @@ -663,7 +663,7 @@ static int legacy_get_tree(struct fs_context *fc) struct dentry *root; if (!(fc->sb_flags & (SB_KERNMOUNT|SB_SUBMOUNT))) { - if (!mount_capable(fc->fs_type, current_user_ns())) + if (!mount_capable(fc->fs_type, fc->user_ns)) return -EPERM; } -- cgit v1.2.3 From 20284ab7427ffac514faf44fd9eb50e5745f4474 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 17:31:45 -0400 Subject: switch mount_capable() to fs_context now both callers of mount_capable() have access to fs_context; the only difference is that for sget_fc() we have the possibility of fc->global being true, while for legacy_get_tree() it's guaranteed to be impossible. Unify to more generic variant... Signed-off-by: Al Viro --- fs/fs_context.c | 2 +- fs/internal.h | 2 +- fs/super.c | 11 +++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/fs_context.c b/fs/fs_context.c index d75ba0eb8c5b..bc5a5f5f1853 100644 --- a/fs/fs_context.c +++ b/fs/fs_context.c @@ -663,7 +663,7 @@ static int legacy_get_tree(struct fs_context *fc) struct dentry *root; if (!(fc->sb_flags & (SB_KERNMOUNT|SB_SUBMOUNT))) { - if (!mount_capable(fc->fs_type, fc->user_ns)) + if (!mount_capable(fc)) return -EPERM; } diff --git a/fs/internal.h b/fs/internal.h index 65db901420af..b089a489da1f 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -114,7 +114,7 @@ extern struct file *alloc_empty_file_noaccount(int, const struct cred *); extern int reconfigure_super(struct fs_context *); extern bool trylock_super(struct super_block *sb); extern struct super_block *user_get_super(dev_t); -extern bool mount_capable(struct file_system_type *, struct user_namespace *); +extern bool mount_capable(struct fs_context *); /* * open.c diff --git a/fs/super.c b/fs/super.c index bdb03255c7ea..d1e2f46bad7e 100644 --- a/fs/super.c +++ b/fs/super.c @@ -476,12 +476,15 @@ void generic_shutdown_super(struct super_block *sb) EXPORT_SYMBOL(generic_shutdown_super); -bool mount_capable(struct file_system_type *type, struct user_namespace *userns) +bool mount_capable(struct fs_context *fc) { - if (!(type->fs_flags & FS_USERNS_MOUNT)) + struct user_namespace *user_ns = fc->global ? &init_user_ns + : fc->user_ns; + + if (!(fc->fs_type->fs_flags & FS_USERNS_MOUNT)) return capable(CAP_SYS_ADMIN); else - return ns_capable(userns, CAP_SYS_ADMIN); + return ns_capable(user_ns, CAP_SYS_ADMIN); } /** @@ -513,7 +516,7 @@ struct super_block *sget_fc(struct fs_context *fc, if (!(fc->sb_flags & SB_KERNMOUNT) && fc->purpose != FS_CONTEXT_FOR_SUBMOUNT) { - if (!mount_capable(fc->fs_type, user_ns)) + if (!mount_capable(fc)) return ERR_PTR(-EPERM); } -- cgit v1.2.3 From 46cf047a945c7a53cb2dc9353a87a9a4e3e778cd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 18:10:24 -0400 Subject: procfs: set ->user_ns before calling ->get_tree() here it's even simpler than in mqueue - pid_ns_prepare_proc() does everything needed anyway. Signed-off-by: Al Viro --- fs/proc/root.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/proc/root.c b/fs/proc/root.c index 8b145e7b9661..74c2c6ab10bd 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -157,8 +157,6 @@ static int proc_get_tree(struct fs_context *fc) { struct proc_fs_context *ctx = fc->fs_private; - put_user_ns(fc->user_ns); - fc->user_ns = get_user_ns(ctx->pid_ns->user_ns); fc->s_fs_info = ctx->pid_ns; return vfs_get_super(fc, vfs_get_keyed_super, proc_fill_super); } @@ -167,8 +165,7 @@ static void proc_fs_context_free(struct fs_context *fc) { struct proc_fs_context *ctx = fc->fs_private; - if (ctx->pid_ns) - put_pid_ns(ctx->pid_ns); + put_pid_ns(ctx->pid_ns); kfree(ctx); } @@ -188,6 +185,8 @@ static int proc_init_fs_context(struct fs_context *fc) return -ENOMEM; ctx->pid_ns = get_pid_ns(task_active_pid_ns(current)); + put_user_ns(fc->user_ns); + fc->user_ns = get_user_ns(ctx->pid_ns->user_ns); fc->fs_private = ctx; fc->ops = &proc_fs_context_ops; return 0; -- cgit v1.2.3 From 059338aae33165179352a26b58d815801072c87d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 18:16:04 -0400 Subject: move mount_capable() calls to vfs_get_tree() sget_fc() is called only from ->get_tree() instances and the only instance not calling it is legacy_get_tree(), which calls mount_capable() directly. In all sget_fc() callers the checks could be moved to the very beginning of ->get_tree() - ->user_ns is not changed in between. So lifting the checks to the only caller of ->get_tree() is OK. Signed-off-by: Al Viro --- fs/fs_context.c | 5 ----- fs/super.c | 12 ++++++------ 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/fs_context.c b/fs/fs_context.c index bc5a5f5f1853..a47ccd5a4a78 100644 --- a/fs/fs_context.c +++ b/fs/fs_context.c @@ -662,11 +662,6 @@ static int legacy_get_tree(struct fs_context *fc) struct super_block *sb; struct dentry *root; - if (!(fc->sb_flags & (SB_KERNMOUNT|SB_SUBMOUNT))) { - if (!mount_capable(fc)) - return -EPERM; - } - root = fc->fs_type->mount(fc->fs_type, fc->sb_flags, fc->source, ctx->legacy_data); if (IS_ERR(root)) diff --git a/fs/super.c b/fs/super.c index d1e2f46bad7e..2c38541cd89f 100644 --- a/fs/super.c +++ b/fs/super.c @@ -514,12 +514,6 @@ struct super_block *sget_fc(struct fs_context *fc, struct user_namespace *user_ns = fc->global ? &init_user_ns : fc->user_ns; int err; - if (!(fc->sb_flags & SB_KERNMOUNT) && - fc->purpose != FS_CONTEXT_FOR_SUBMOUNT) { - if (!mount_capable(fc)) - return ERR_PTR(-EPERM); - } - retry: spin_lock(&sb_lock); if (test) { @@ -1421,6 +1415,12 @@ int vfs_get_tree(struct fs_context *fc) if (fc->root) return -EBUSY; + if (!(fc->sb_flags & SB_KERNMOUNT) && + fc->purpose != FS_CONTEXT_FOR_SUBMOUNT) { + if (!mount_capable(fc)) + return -EPERM; + } + /* Get the mountable root in fc->root, with a ref on the root and a ref * on the superblock. */ -- cgit v1.2.3 From c3aabf0780a506225b53bfe2b5177dd5dfec093d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 13 May 2019 12:57:22 -0400 Subject: move mount_capable() further out Call graph of vfs_get_tree(): vfs_fsconfig_locked() # neither kernmount, nor submount do_new_mount() # neither kernmount, nor submount fc_mount() afs_mntpt_do_automount() # submount mount_one_hugetlbfs() # kernmount pid_ns_prepare_proc() # kernmount mq_create_mount() # kernmount vfs_kern_mount() simple_pin_fs() # kernmount vfs_submount() # submount kern_mount() # kernmount init_mount_tree() btrfs_mount() nfs_do_root_mount() The first two need the check (unconditionally). init_mount_tree() is setting rootfs up; any capability checks make zero sense for that one. And btrfs_mount()/ nfs_do_root_mount() have the checks already done in their callers. IOW, we can shift mount_capable() handling into the two callers - one in the normal case of mount(2), another - in fsconfig(2) handling of FSCONFIG_CMD_CREATE. I.e. the syscalls that set a new filesystem up. Signed-off-by: Al Viro --- fs/fsopen.c | 2 ++ fs/namespace.c | 2 ++ fs/super.c | 6 ------ 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/fsopen.c b/fs/fsopen.c index c2891e933ef1..390172772f55 100644 --- a/fs/fsopen.c +++ b/fs/fsopen.c @@ -230,6 +230,8 @@ static int vfs_fsconfig_locked(struct fs_context *fc, int cmd, case FSCONFIG_CMD_CREATE: if (fc->phase != FS_CONTEXT_CREATE_PARAMS) return -EBUSY; + if (!mount_capable(fc)) + return -EPERM; fc->phase = FS_CONTEXT_CREATING; ret = vfs_get_tree(fc); if (ret) diff --git a/fs/namespace.c b/fs/namespace.c index ffb13f0562b0..1141641dff96 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2786,6 +2786,8 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags, err = vfs_parse_fs_string(fc, "source", name, strlen(name)); if (!err) err = parse_monolithic_mount_data(fc, data); + if (!err && !mount_capable(fc)) + err = -EPERM; if (!err) err = vfs_get_tree(fc); if (!err) diff --git a/fs/super.c b/fs/super.c index 2c38541cd89f..72b4a5afcfd6 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1415,12 +1415,6 @@ int vfs_get_tree(struct fs_context *fc) if (fc->root) return -EBUSY; - if (!(fc->sb_flags & SB_KERNMOUNT) && - fc->purpose != FS_CONTEXT_FOR_SUBMOUNT) { - if (!mount_capable(fc)) - return -EPERM; - } - /* Get the mountable root in fc->root, with a ref on the root and a ref * on the superblock. */ -- cgit v1.2.3 From 7cdfa44227b0d8842d46a775cebe4311150cb8f2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:22 +0000 Subject: vfs: Fix refcounting of filenames in fs_parser Fix an overput in which filename_lookup() unconditionally drops a ref to the filename it was given, but this isn't taken account of in the caller, fs_lookup_param(). Addresses-Coverity-ID: 1443811 ("Use after free") Signed-off-by: David Howells --- fs/fs_parser.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/fs_parser.c b/fs/fs_parser.c index 570d71043acf..3a1697c2f72f 100644 --- a/fs/fs_parser.c +++ b/fs/fs_parser.c @@ -268,6 +268,7 @@ int fs_lookup_param(struct fs_context *fc, return invalf(fc, "%s: not usable as path", param->key); } + f->refcnt++; /* filename_lookup() drops our ref. */ ret = filename_lookup(param->dirfd, f, flags, _path, NULL); if (ret < 0) { errorf(fc, "%s: Lookup failure for '%s'", param->key, f->name); -- cgit v1.2.3 From c80fa7c8301c10ad10d997b9e86b4aeac5923b3e Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: vfs: Provide sb->s_iflags settings in fs_context struct Provide a field in the fs_context struct through which bits in the sb->s_iflags superblock field can be set. Signed-off-by: David Howells cc: linux-fsdevel@vger.kernel.org --- fs/super.c | 1 + include/linux/fs_context.h | 1 + 2 files changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/super.c b/fs/super.c index 72b4a5afcfd6..f836b67abffe 100644 --- a/fs/super.c +++ b/fs/super.c @@ -540,6 +540,7 @@ retry: } fc->s_fs_info = NULL; s->s_type = fc->fs_type; + s->s_iflags |= fc->s_iflags; strlcpy(s->s_id, s->s_type->name, sizeof(s->s_id)); list_add_tail(&s->s_list, &super_blocks); hlist_add_head(&s->s_instances, &s->s_type->fs_supers); diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h index 1f966670c8dc..c995b852ba40 100644 --- a/include/linux/fs_context.h +++ b/include/linux/fs_context.h @@ -103,6 +103,7 @@ struct fs_context { void *s_fs_info; /* Proposed s_fs_info */ unsigned int sb_flags; /* Proposed superblock flags (SB_*) */ unsigned int sb_flags_mask; /* Superblock flags that were changed */ + unsigned int s_iflags; /* OR'd with sb->s_iflags */ unsigned int lsm_flags; /* Information flags from the fs to the LSM */ enum fs_context_purpose purpose:8; enum fs_context_phase phase:8; /* The phase the context is in */ -- cgit v1.2.3 From 31d6d5ce53400d6dc58e29ddd8dc184b3ba89d66 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: vfs: Provide a mount_pseudo-replacement for the new mount API Provide a function, init_pseudo(), that provides a common infrastructure for converting pseudo-filesystems that can never be mountable. [AV: once all users of mount_pseudo_xattr() get converted, it will be folded into pseudo_fs_get_tree()] Signed-off-by: David Howells cc: linux-fsdevel@vger.kernel.org --- fs/libfs.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pseudo_fs.h | 16 ++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 include/linux/pseudo_fs.h (limited to 'fs') diff --git a/fs/libfs.c b/fs/libfs.c index 030e545f586e..edef70d35438 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -16,6 +16,8 @@ #include #include #include /* sync_mapping_buffers */ +#include +#include #include @@ -235,6 +237,50 @@ static const struct super_operations simple_super_operations = { .statfs = simple_statfs, }; +static int pseudo_fs_get_tree(struct fs_context *fc) +{ + struct pseudo_fs_context *ctx = fc->fs_private; + struct dentry *root; + + root = mount_pseudo_xattr(fc->fs_type, + ctx->ops, ctx->xattr, + ctx->dops, ctx->magic); + if (IS_ERR(root)) + return PTR_ERR(root); + + fc->root = root; + return 0; +} + +static void pseudo_fs_free(struct fs_context *fc) +{ + kfree(fc->fs_private); +} + +static const struct fs_context_operations pseudo_fs_context_ops = { + .free = pseudo_fs_free, + .get_tree = pseudo_fs_get_tree, +}; + +/* + * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that + * will never be mountable) + */ +struct pseudo_fs_context *init_pseudo(struct fs_context *fc, + unsigned long magic) +{ + struct pseudo_fs_context *ctx; + + ctx = kzalloc(sizeof(struct pseudo_fs_context), GFP_KERNEL); + if (likely(ctx)) { + ctx->magic = magic; + fc->fs_private = ctx; + fc->ops = &pseudo_fs_context_ops; + } + return ctx; +} +EXPORT_SYMBOL(init_pseudo); + /* * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that * will never be mountable) diff --git a/include/linux/pseudo_fs.h b/include/linux/pseudo_fs.h new file mode 100644 index 000000000000..eceda1d1407a --- /dev/null +++ b/include/linux/pseudo_fs.h @@ -0,0 +1,16 @@ +#ifndef __LINUX_PSEUDO_FS__ +#define __LINUX_PSEUDO_FS__ + +#include + +struct pseudo_fs_context { + const struct super_operations *ops; + const struct xattr_handler **xattr; + const struct dentry_operations *dops; + unsigned long magic; +}; + +struct pseudo_fs_context *init_pseudo(struct fs_context *fc, + unsigned long magic); + +#endif -- cgit v1.2.3 From 52db59df17c0cd3ee4071a75a8509287a662abac Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: vfs: Convert aio to use the new mount API Convert the aio 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 cc: Benjamin LaHaise cc: linux-aio@kvack.org Signed-off-by: Al Viro --- fs/aio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index 09bc35fa6810..17f4441fd583 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -249,14 +250,12 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) return file; } -static struct dentry *aio_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int aio_init_fs_context(struct fs_context *fc) { - struct dentry *root = mount_pseudo(fs_type, NULL, NULL, AIO_RING_MAGIC); - - if (!IS_ERR(root)) - root->d_sb->s_iflags |= SB_I_NOEXEC; - return root; + if (!init_pseudo(fc, AIO_RING_MAGIC)) + return -ENOMEM; + fc->s_iflags |= SB_I_NOEXEC; + return 0; } /* aio_setup @@ -267,7 +266,7 @@ static int __init aio_setup(void) { static struct file_system_type aio_fs = { .name = "aio", - .mount = aio_mount, + .init_fs_context = aio_init_fs_context, .kill_sb = kill_anon_super, }; aio_mnt = kern_mount(&aio_fs); -- cgit v1.2.3 From 33cada40b51f083d8508e66f96c646640f773835 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: vfs: Convert anon_inodes to use the new mount API Convert the anon_inodes 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 cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/anon_inodes.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 644d0837aafe..7ea017cb1dd4 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -38,16 +39,18 @@ static const struct dentry_operations anon_inodefs_dentry_operations = { .d_dname = anon_inodefs_dname, }; -static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int anon_inodefs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, &anon_inodefs_dentry_operations, - ANON_INODE_FS_MAGIC); + struct pseudo_fs_context *ctx = init_pseudo(fc, ANON_INODE_FS_MAGIC); + if (!ctx) + return -ENOMEM; + ctx->dops = &anon_inodefs_dentry_operations; + return 0; } static struct file_system_type anon_inode_fs_type = { .name = "anon_inodefs", - .mount = anon_inodefs_mount, + .init_fs_context = anon_inodefs_init_fs_context, .kill_sb = kill_anon_super, }; -- cgit v1.2.3 From 9030d16eb8adcbf9e80d20b909856c6fdabfdec4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: vfs: Convert bdev to use the new mount API Convert the bdev 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 cc: Jens Axboe cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/block_dev.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index 3143da7b0998..1d051b962159 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -833,19 +834,19 @@ static const struct super_operations bdev_sops = { .evict_inode = bdev_evict_inode, }; -static struct dentry *bd_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bd_init_fs_context(struct fs_context *fc) { - struct dentry *dent; - dent = mount_pseudo(fs_type, &bdev_sops, NULL, BDEVFS_MAGIC); - if (!IS_ERR(dent)) - dent->d_sb->s_iflags |= SB_I_CGROUPWB; - return dent; + struct pseudo_fs_context *ctx = init_pseudo(fc, BDEVFS_MAGIC); + if (!ctx) + return -ENOMEM; + fc->s_iflags |= SB_I_CGROUPWB; + ctx->ops = &bdev_sops; + return 0; } static struct file_system_type bd_type = { .name = "bdev", - .mount = bd_mount, + .init_fs_context = bd_init_fs_context, .kill_sb = kill_anon_super, }; -- cgit v1.2.3 From 059b20d9da69d3a9bfb7ab00d1e5a3114a31c822 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: vfs: Convert nsfs to use the new mount API Convert the nsfs 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 cc: Eric W. Biederman cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/nsfs.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/nsfs.c b/fs/nsfs.c index b3c49ddc0f85..a0431642c6b5 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include @@ -258,15 +259,20 @@ static const struct super_operations nsfs_ops = { .evict_inode = nsfs_evict, .show_path = nsfs_show_path, }; -static struct dentry *nsfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + +static int nsfs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, &nsfs_ops, - &ns_dentry_operations, NSFS_MAGIC); + struct pseudo_fs_context *ctx = init_pseudo(fc, NSFS_MAGIC); + if (!ctx) + return -ENOMEM; + ctx->ops = &nsfs_ops; + ctx->dops = &ns_dentry_operations; + return 0; } + static struct file_system_type nsfs = { .name = "nsfs", - .mount = nsfs_mount, + .init_fs_context = nsfs_init_fs_context, .kill_sb = kill_anon_super, }; -- cgit v1.2.3 From 4fa7ec5db7e731a3db26b9647f39b0595f74347d Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: vfs: Convert pipe to use the new mount API Convert the pipe 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 cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/pipe.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/pipe.c b/fs/pipe.c index 99a023730e6f..8a2ab2f974bd 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1182,16 +1183,20 @@ static const struct super_operations pipefs_ops = { * any operations on the root directory. However, we need a non-trivial * d_name - pipe: will go nicely and kill the special-casing in procfs. */ -static struct dentry *pipefs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + +static int pipefs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, &pipefs_ops, - &pipefs_dentry_operations, PIPEFS_MAGIC); + struct pseudo_fs_context *ctx = init_pseudo(fc, PIPEFS_MAGIC); + if (!ctx) + return -ENOMEM; + ctx->ops = &pipefs_ops; + ctx->dops = &pipefs_dentry_operations; + return 0; } static struct file_system_type pipe_fs_type = { .name = "pipefs", - .mount = pipefs_mount, + .init_fs_context = pipefs_init_fs_context, .kill_sb = kill_anon_super, }; -- cgit v1.2.3 From 389e22fb46eb1f48b089060c30030790e7a41033 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:25 +0000 Subject: vfs: Convert btrfs_test to use the new mount API Convert the btrfs_test 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 Acked-by: David Sterba cc: Chris Mason cc: Josef Bacik cc: linux-btrfs@vger.kernel.org Signed-off-by: Al Viro --- fs/btrfs/tests/btrfs-tests.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c index 6da54323eaf8..1e3ba4949399 100644 --- a/fs/btrfs/tests/btrfs-tests.c +++ b/fs/btrfs/tests/btrfs-tests.c @@ -5,6 +5,7 @@ #include #include +#include #include #include "btrfs-tests.h" #include "../ctree.h" @@ -32,17 +33,19 @@ static const struct super_operations btrfs_test_super_ops = { .destroy_inode = btrfs_test_destroy_inode, }; -static struct dentry *btrfs_test_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) + +static int btrfs_test_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, &btrfs_test_super_ops, - NULL, BTRFS_TEST_MAGIC); + struct pseudo_fs_context *ctx = init_pseudo(fc, BTRFS_TEST_MAGIC); + if (!ctx) + return -ENOMEM; + ctx->ops = &btrfs_test_super_ops; + return 0; } static struct file_system_type test_type = { .name = "btrfs_test_fs", - .mount = btrfs_test_mount, + .init_fs_context = btrfs_test_init_fs_context, .kill_sb = kill_anon_super, }; -- cgit v1.2.3 From 8d9e46d80777b484f8f0945c317ad618224d7811 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 11 May 2019 11:43:59 -0400 Subject: fold mount_pseudo_xattr() into pseudo_fs_get_tree() ... now that all other callers are gone Signed-off-by: Al Viro --- fs/libfs.c | 88 +++++++++++++++++++++--------------------------------- include/linux/fs.h | 13 -------- 2 files changed, 34 insertions(+), 67 deletions(-) (limited to 'fs') diff --git a/fs/libfs.c b/fs/libfs.c index edef70d35438..7df3c9a85f6b 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -240,16 +240,43 @@ static const struct super_operations simple_super_operations = { static int pseudo_fs_get_tree(struct fs_context *fc) { struct pseudo_fs_context *ctx = fc->fs_private; - struct dentry *root; + struct super_block *s; + struct inode *root; - root = mount_pseudo_xattr(fc->fs_type, - ctx->ops, ctx->xattr, - ctx->dops, ctx->magic); - if (IS_ERR(root)) - return PTR_ERR(root); + s = sget_userns(fc->fs_type, NULL, set_anon_super, SB_KERNMOUNT|SB_NOUSER, + &init_user_ns, NULL); + if (IS_ERR(s)) + return PTR_ERR(s); - fc->root = root; + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_blocksize = PAGE_SIZE; + s->s_blocksize_bits = PAGE_SHIFT; + s->s_magic = ctx->magic; + s->s_op = ctx->ops ?: &simple_super_operations; + s->s_xattr = ctx->xattr; + s->s_time_gran = 1; + root = new_inode(s); + if (!root) + goto Enomem; + /* + * since this is the first inode, make it number 1. New inodes created + * after this must take care not to collide with it (by passing + * max_reserved of 1 to iunique). + */ + root->i_ino = 1; + root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; + root->i_atime = root->i_mtime = root->i_ctime = current_time(root); + s->s_root = d_make_root(root); + if (!s->s_root) + goto Enomem; + s->s_d_op = ctx->dops; + s->s_flags |= SB_ACTIVE; + fc->root = dget(s->s_root); return 0; + +Enomem: + deactivate_locked_super(s); + return -ENOMEM; } static void pseudo_fs_free(struct fs_context *fc) @@ -281,53 +308,6 @@ struct pseudo_fs_context *init_pseudo(struct fs_context *fc, } EXPORT_SYMBOL(init_pseudo); -/* - * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that - * will never be mountable) - */ -struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, - const struct super_operations *ops, const struct xattr_handler **xattr, - const struct dentry_operations *dops, unsigned long magic) -{ - struct super_block *s; - struct inode *root; - - s = sget_userns(fs_type, NULL, set_anon_super, SB_KERNMOUNT|SB_NOUSER, - &init_user_ns, NULL); - if (IS_ERR(s)) - return ERR_CAST(s); - - s->s_maxbytes = MAX_LFS_FILESIZE; - s->s_blocksize = PAGE_SIZE; - s->s_blocksize_bits = PAGE_SHIFT; - s->s_magic = magic; - s->s_op = ops ? ops : &simple_super_operations; - s->s_xattr = xattr; - s->s_time_gran = 1; - root = new_inode(s); - if (!root) - goto Enomem; - /* - * since this is the first inode, make it number 1. New inodes created - * after this must take care not to collide with it (by passing - * max_reserved of 1 to iunique). - */ - root->i_ino = 1; - root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; - root->i_atime = root->i_mtime = root->i_ctime = current_time(root); - s->s_root = d_make_root(root); - if (!s->s_root) - goto Enomem; - s->s_d_op = dops; - s->s_flags |= SB_ACTIVE; - return dget(s->s_root); - -Enomem: - deactivate_locked_super(s); - return ERR_PTR(-ENOMEM); -} -EXPORT_SYMBOL(mount_pseudo_xattr); - int simple_open(struct inode *inode, struct file *file) { if (inode->i_private) diff --git a/include/linux/fs.h b/include/linux/fs.h index 790342cf4df9..d625acabbfcf 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2254,19 +2254,6 @@ struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), int flags, void *data); -extern struct dentry *mount_pseudo_xattr(struct file_system_type *, - const struct super_operations *ops, - const struct xattr_handler **xattr, - const struct dentry_operations *dops, - unsigned long); - -static inline struct dentry * -mount_pseudo(struct file_system_type *fs_type, - const struct super_operations *ops, - const struct dentry_operations *dops, unsigned long magic) -{ - return mount_pseudo_xattr(fs_type, ops, NULL, dops, magic); -} /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ #define fops_get(fops) \ -- cgit v1.2.3 From db2c246a091efe2e49aeb3fe0cf6ed2affbddf37 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:26 +0000 Subject: vfs: Use sget_fc() for pseudo-filesystems Signed-off-by: David Howells cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/libfs.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/libfs.c b/fs/libfs.c index 7df3c9a85f6b..7e6811ba4edd 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -237,17 +237,11 @@ static const struct super_operations simple_super_operations = { .statfs = simple_statfs, }; -static int pseudo_fs_get_tree(struct fs_context *fc) +static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc) { struct pseudo_fs_context *ctx = fc->fs_private; - struct super_block *s; struct inode *root; - s = sget_userns(fc->fs_type, NULL, set_anon_super, SB_KERNMOUNT|SB_NOUSER, - &init_user_ns, NULL); - if (IS_ERR(s)) - return PTR_ERR(s); - s->s_maxbytes = MAX_LFS_FILESIZE; s->s_blocksize = PAGE_SIZE; s->s_blocksize_bits = PAGE_SHIFT; @@ -257,7 +251,8 @@ static int pseudo_fs_get_tree(struct fs_context *fc) s->s_time_gran = 1; root = new_inode(s); if (!root) - goto Enomem; + return -ENOMEM; + /* * since this is the first inode, make it number 1. New inodes created * after this must take care not to collide with it (by passing @@ -268,15 +263,14 @@ static int pseudo_fs_get_tree(struct fs_context *fc) root->i_atime = root->i_mtime = root->i_ctime = current_time(root); s->s_root = d_make_root(root); if (!s->s_root) - goto Enomem; + return -ENOMEM; s->s_d_op = ctx->dops; - s->s_flags |= SB_ACTIVE; - fc->root = dget(s->s_root); return 0; +} -Enomem: - deactivate_locked_super(s); - return -ENOMEM; +static int pseudo_fs_get_tree(struct fs_context *fc) +{ + return vfs_get_super(fc, vfs_get_independent_super, pseudo_fs_fill_super); } static void pseudo_fs_free(struct fs_context *fc) @@ -303,6 +297,8 @@ struct pseudo_fs_context *init_pseudo(struct fs_context *fc, ctx->magic = magic; fc->fs_private = ctx; fc->ops = &pseudo_fs_context_ops; + fc->sb_flags |= SB_NOUSER; + fc->global = true; } return ctx; } -- cgit v1.2.3 From 023d066a0d0a87696c04b0de2ceae53063d0b655 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:28 +0000 Subject: vfs: Kill sget_userns() Kill sget_userns(), folding it into sget() as that's the only remaining user. Signed-off-by: David Howells cc: linux-fsdevel@vger.kernel.org --- fs/super.c | 54 ++++++++++++++++-------------------------------------- include/linux/fs.h | 5 ----- 2 files changed, 16 insertions(+), 43 deletions(-) (limited to 'fs') diff --git a/fs/super.c b/fs/super.c index f836b67abffe..ca2302501d32 100644 --- a/fs/super.c +++ b/fs/super.c @@ -563,24 +563,31 @@ share_extant_sb: EXPORT_SYMBOL(sget_fc); /** - * sget_userns - find or create a superblock - * @type: filesystem type superblock should belong to - * @test: comparison callback - * @set: setup callback - * @flags: mount flags - * @user_ns: User namespace for the super_block - * @data: argument to each of them + * sget - find or create a superblock + * @type: filesystem type superblock should belong to + * @test: comparison callback + * @set: setup callback + * @flags: mount flags + * @data: argument to each of them */ -struct super_block *sget_userns(struct file_system_type *type, +struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), - int flags, struct user_namespace *user_ns, + int flags, void *data) { + struct user_namespace *user_ns = current_user_ns(); struct super_block *s = NULL; struct super_block *old; int err; + /* We don't yet pass the user namespace of the parent + * mount through to here so always use &init_user_ns + * until that changes. + */ + if (flags & SB_SUBMOUNT) + user_ns = &init_user_ns; + retry: spin_lock(&sb_lock); if (test) { @@ -621,35 +628,6 @@ retry: register_shrinker_prepared(&s->s_shrink); return s; } - -EXPORT_SYMBOL(sget_userns); - -/** - * sget - find or create a superblock - * @type: filesystem type superblock should belong to - * @test: comparison callback - * @set: setup callback - * @flags: mount flags - * @data: argument to each of them - */ -struct super_block *sget(struct file_system_type *type, - int (*test)(struct super_block *,void *), - int (*set)(struct super_block *,void *), - int flags, - void *data) -{ - struct user_namespace *user_ns = current_user_ns(); - - /* We don't yet pass the user namespace of the parent - * mount through to here so always use &init_user_ns - * until that changes. - */ - if (flags & SB_SUBMOUNT) - user_ns = &init_user_ns; - - return sget_userns(type, test, set, flags, user_ns, data); -} - EXPORT_SYMBOL(sget); void drop_super(struct super_block *sb) diff --git a/include/linux/fs.h b/include/linux/fs.h index d625acabbfcf..71421856ff2c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2245,11 +2245,6 @@ void free_anon_bdev(dev_t); struct super_block *sget_fc(struct fs_context *fc, int (*test)(struct super_block *, struct fs_context *), int (*set)(struct super_block *, struct fs_context *)); -struct super_block *sget_userns(struct file_system_type *type, - int (*test)(struct super_block *,void *), - int (*set)(struct super_block *,void *), - int flags, struct user_namespace *user_ns, - void *data); struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), -- cgit v1.2.3 From 2ac295d4f0c095310addbcb03d91d2a4c9f7d435 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Jun 2019 20:48:55 -0400 Subject: convenience helper get_tree_nodev() counterpart of mount_nodev(). Switch hugetlb and pseudo to it. Signed-off-by: Al Viro --- fs/hugetlbfs/inode.c | 2 +- fs/libfs.c | 2 +- fs/super.c | 8 ++++++++ include/linux/fs_context.h | 3 +++ 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 1dcc57189382..a478df035651 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -1299,7 +1299,7 @@ static int hugetlbfs_get_tree(struct fs_context *fc) int err = hugetlbfs_validate(fc); if (err) return err; - return vfs_get_super(fc, vfs_get_independent_super, hugetlbfs_fill_super); + return get_tree_nodev(fc, hugetlbfs_fill_super); } static void hugetlbfs_fs_context_free(struct fs_context *fc) diff --git a/fs/libfs.c b/fs/libfs.c index 7e6811ba4edd..c9463dc6a5d4 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -270,7 +270,7 @@ static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc) static int pseudo_fs_get_tree(struct fs_context *fc) { - return vfs_get_super(fc, vfs_get_independent_super, pseudo_fs_fill_super); + return get_tree_nodev(fc, pseudo_fs_fill_super); } static void pseudo_fs_free(struct fs_context *fc) diff --git a/fs/super.c b/fs/super.c index ca2302501d32..3318225b0878 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1198,6 +1198,14 @@ int vfs_get_super(struct fs_context *fc, } EXPORT_SYMBOL(vfs_get_super); +int get_tree_nodev(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)) +{ + return vfs_get_super(fc, vfs_get_independent_super, fill_super); +} +EXPORT_SYMBOL(get_tree_nodev); + #ifdef CONFIG_BLOCK static int set_bdev_super(struct super_block *s, void *data) { diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h index c995b852ba40..38b1ec918a4e 100644 --- a/include/linux/fs_context.h +++ b/include/linux/fs_context.h @@ -151,6 +151,9 @@ extern int vfs_get_super(struct fs_context *fc, enum vfs_get_super_keying keying, int (*fill_super)(struct super_block *sb, struct fs_context *fc)); +extern int get_tree_nodev(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)); extern const struct file_operations fscontext_fops; -- cgit v1.2.3 From c23a0bbab30cc1714b6b1d6a1c153a5ccab3f0d8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 22 May 2019 21:23:39 -0400 Subject: convenience helper: get_tree_single() counterpart of mount_single(); switch fusectl to it Signed-off-by: Al Viro --- fs/fuse/control.c | 2 +- fs/super.c | 8 ++++++++ include/linux/fs_context.h | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 14ce1e47f980..c23f6f243ad4 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -346,7 +346,7 @@ static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fctx) static int fuse_ctl_get_tree(struct fs_context *fc) { - return vfs_get_super(fc, vfs_get_single_super, fuse_ctl_fill_super); + return get_tree_single(fc, fuse_ctl_fill_super); } static const struct fs_context_operations fuse_ctl_context_ops = { diff --git a/fs/super.c b/fs/super.c index 3318225b0878..113c58f19425 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1206,6 +1206,14 @@ int get_tree_nodev(struct fs_context *fc, } EXPORT_SYMBOL(get_tree_nodev); +int get_tree_single(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)) +{ + return vfs_get_super(fc, vfs_get_single_super, fill_super); +} +EXPORT_SYMBOL(get_tree_single); + #ifdef CONFIG_BLOCK static int set_bdev_super(struct super_block *s, void *data) { diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h index 38b1ec918a4e..1775969e000d 100644 --- a/include/linux/fs_context.h +++ b/include/linux/fs_context.h @@ -154,6 +154,9 @@ extern int vfs_get_super(struct fs_context *fc, extern int get_tree_nodev(struct fs_context *fc, int (*fill_super)(struct super_block *sb, struct fs_context *fc)); +extern int get_tree_single(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)); extern const struct file_operations fscontext_fops; -- cgit v1.2.3 From bc99a664e9be24e49e09da1250ede0c598d958d1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:28 +0000 Subject: vfs: Convert binfmt_misc to use the new mount API Convert the binfmt_misc 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 cc: Alexander Viro cc: linux-fsdevel@vger.kernel.org Signed-off-by: Al Viro --- fs/binfmt_misc.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index aa4a7a23ff99..46a3d149bb7f 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -820,7 +821,7 @@ static const struct super_operations s_ops = { .evict_inode = bm_evict_inode, }; -static int bm_fill_super(struct super_block *sb, void *data, int silent) +static int bm_fill_super(struct super_block *sb, struct fs_context *fc) { int err; static const struct tree_descr bm_files[] = { @@ -835,10 +836,19 @@ static int bm_fill_super(struct super_block *sb, void *data, int silent) return err; } -static struct dentry *bm_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bm_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, bm_fill_super); + return get_tree_single(fc, bm_fill_super); +} + +static const struct fs_context_operations bm_context_ops = { + .get_tree = bm_get_tree, +}; + +static int bm_init_fs_context(struct fs_context *fc) +{ + fc->ops = &bm_context_ops; + return 0; } static struct linux_binfmt misc_format = { @@ -849,7 +859,7 @@ static struct linux_binfmt misc_format = { static struct file_system_type bm_fs_type = { .owner = THIS_MODULE, .name = "binfmt_misc", - .mount = bm_mount, + .init_fs_context = bm_init_fs_context, .kill_sb = kill_litter_super, }; MODULE_ALIAS_FS("binfmt_misc"); -- cgit v1.2.3 From 6bc62f2067d30f90621c42a2794c2515eff7bf11 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:29 +0000 Subject: vfs: Convert configfs to use the new mount API Convert the configfs 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 cc: Joel Becker cc: Christoph Hellwig Signed-off-by: Al Viro --- fs/configfs/mount.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index cfd91320e869..13c93715864b 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ static struct configfs_dirent configfs_root = { .s_iattr = NULL, }; -static int configfs_fill_super(struct super_block *sb, void *data, int silent) +static int configfs_fill_super(struct super_block *sb, struct fs_context *fc) { struct inode *inode; struct dentry *root; @@ -102,16 +103,25 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct dentry *configfs_do_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int configfs_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, configfs_fill_super); + return get_tree_single(fc, configfs_fill_super); +} + +static const struct fs_context_operations configfs_context_ops = { + .get_tree = configfs_get_tree, +}; + +static int configfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &configfs_context_ops; + return 0; } static struct file_system_type configfs_fs_type = { .owner = THIS_MODULE, .name = "configfs", - .mount = configfs_do_mount, + .init_fs_context = configfs_init_fs_context, .kill_sb = kill_litter_super, }; MODULE_ALIAS_FS("configfs"); -- cgit v1.2.3 From 4799974555de565df0d0aca86c15bbea70105a19 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:29 +0000 Subject: vfs: Convert efivarfs to use the new mount API Convert the efivarfs 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. [AV: get rid of efivarfs_sb nonsense - it has never been used] See Documentation/filesystems/mount_api.txt for more information. Signed-off-by: David Howells cc: Matthew Garrett cc: Jeremy Kerr cc: Ard Biesheuvel cc: linux-efi@vger.kernel.org Signed-off-by: Al Viro --- fs/efivarfs/super.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index 5b68e4294faa..124f1aa9ab03 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,6 @@ static const struct super_operations efivarfs_ops = { .evict_inode = efivarfs_evict_inode, }; -static struct super_block *efivarfs_sb; - /* * Compare two efivarfs file names. * @@ -191,14 +190,12 @@ static int efivarfs_destroy(struct efivar_entry *entry, void *data) return 0; } -static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) +static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc) { struct inode *inode = NULL; struct dentry *root; int err; - efivarfs_sb = sb; - sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; @@ -226,16 +223,24 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) return err; } -static struct dentry *efivarfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int efivarfs_get_tree(struct fs_context *fc) +{ + return get_tree_single(fc, efivarfs_fill_super); +} + +static const struct fs_context_operations efivarfs_context_ops = { + .get_tree = efivarfs_get_tree, +}; + +static int efivarfs_init_fs_context(struct fs_context *fc) { - return mount_single(fs_type, flags, data, efivarfs_fill_super); + fc->ops = &efivarfs_context_ops; + return 0; } static void efivarfs_kill_sb(struct super_block *sb) { kill_litter_super(sb); - efivarfs_sb = NULL; /* Remove all entries and destroy */ __efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL, NULL); @@ -244,7 +249,7 @@ static void efivarfs_kill_sb(struct super_block *sb) static struct file_system_type efivarfs_type = { .owner = THIS_MODULE, .name = "efivarfs", - .mount = efivarfs_mount, + .init_fs_context = efivarfs_init_fs_context, .kill_sb = efivarfs_kill_sb, }; -- cgit v1.2.3 From 7ab2fa7693c3f0ce8445fd4e9e4e58e34e6a2213 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: vfs: Convert openpromfs to use the new mount API Convert the openpromfs 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 Signed-off-by: Al Viro --- fs/openpromfs/inode.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 46655e454c55..74502de3f8d9 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -374,7 +375,7 @@ static const struct super_operations openprom_sops = { .remount_fs = openprom_remount, }; -static int openprom_fill_super(struct super_block *s, void *data, int silent) +static int openprom_fill_super(struct super_block *s, struct fs_context *fc) { struct inode *root_inode; struct op_inode_info *oi; @@ -408,16 +409,25 @@ out_no_root: return ret; } -static struct dentry *openprom_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int openpromfs_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, openprom_fill_super); + return get_tree_single(fc, openprom_fill_super); +} + +static const struct fs_context_operations openpromfs_context_ops = { + .get_tree = openpromfs_get_tree, +}; + +static int openpromfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &openpromfs_context_ops; + return 0; } static struct file_system_type openprom_fs_type = { .owner = THIS_MODULE, .name = "openpromfs", - .mount = openprom_mount, + .init_fs_context = openpromfs_init_fs_context, .kill_sb = kill_anon_super, }; MODULE_ALIAS_FS("openpromfs"); -- cgit v1.2.3 From 14a253ce4210cd2ef133b392062477e9d656db4a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 May 2019 15:59:57 -0400 Subject: init_rootfs(): don't bother with init_ramfs_fs() the only thing done by the latter is making ramfs visible to mount(2); we don't need it there - rootfs is separate and, in fact, made visible to mount(2) in the same init_rootfs(). Signed-off-by: Al Viro --- fs/ramfs/inode.c | 6 +----- include/linux/ramfs.h | 1 - init/do_mounts.c | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 11201b2d06b9..733c6b4193dc 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -266,12 +266,8 @@ static struct file_system_type ramfs_fs_type = { .fs_flags = FS_USERNS_MOUNT, }; -int __init init_ramfs_fs(void) +static int __init init_ramfs_fs(void) { - static unsigned long once; - - if (test_and_set_bit(0, &once)) - return 0; return register_filesystem(&ramfs_fs_type); } fs_initcall(init_ramfs_fs); diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 5ef7d54caac2..ee582bdb7fda 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h @@ -19,7 +19,6 @@ extern int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize); extern const struct file_operations ramfs_file_operations; extern const struct vm_operations_struct generic_file_vm_ops; -extern int __init init_ramfs_fs(void); int ramfs_fill_super(struct super_block *sb, void *data, int silent); diff --git a/init/do_mounts.c b/init/do_mounts.c index f8c230c77035..c170d8b309b1 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -658,8 +658,6 @@ int __init init_rootfs(void) (!root_fs_names || strstr(root_fs_names, "tmpfs"))) { err = shmem_init(); is_tmpfs = true; - } else { - err = init_ramfs_fs(); } if (err) -- cgit v1.2.3 From fd3e007f6c6a0f677e4ee8aca4b9bab8ad6cab9a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 May 2019 17:48:35 -0400 Subject: don't bother with registering rootfs init_mount_tree() can get to rootfs_fs_type directly and that simplifies a lot of things. We don't need to register it, we don't need to look it up *and* we don't need to bother with preventing subsequent userland mounts. That's the way we should've done that from the very beginning. There is a user-visible change, namely the disappearance of "rootfs" from /proc/filesystems. Note that it's been unmountable all along and it didn't show up in /proc/mounts; however, it *is* a user-visible change and theoretically some script might've been using its presence in /proc/filesystems to tell 2.4.11+ from earlier kernels. *IF* any complaints about behaviour change do show up, we could fake it in /proc/filesystems. I very much doubt we'll have to, though. Signed-off-by: Al Viro --- fs/namespace.c | 7 +------ include/linux/init.h | 3 +++ init/do_mounts.c | 15 ++------------- 3 files changed, 6 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/namespace.c b/fs/namespace.c index 1141641dff96..2db2f4c36c50 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3686,13 +3686,8 @@ static void __init init_mount_tree(void) struct mount *m; struct mnt_namespace *ns; struct path root; - struct file_system_type *type; - type = get_fs_type("rootfs"); - if (!type) - panic("Can't find rootfs type"); - mnt = vfs_kern_mount(type, 0, "rootfs", NULL); - put_filesystem(type); + mnt = vfs_kern_mount(&rootfs_fs_type, 0, "rootfs", NULL); if (IS_ERR(mnt)) panic("Can't create rootfs"); diff --git a/include/linux/init.h b/include/linux/init.h index 5255069f5a9f..cbe93521397e 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -137,6 +137,8 @@ extern initcall_entry_t __con_initcall_start[], __con_initcall_end[]; /* Used for contructor calls. */ typedef void (*ctor_fn_t)(void); +struct file_system_type; + /* Defined in init/main.c */ extern int do_one_initcall(initcall_t fn); extern char __initdata boot_command_line[]; @@ -147,6 +149,7 @@ extern unsigned int reset_devices; void setup_arch(char **); void prepare_namespace(void); int __init init_rootfs(void); +extern struct file_system_type rootfs_fs_type; #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX) extern bool rodata_enabled; diff --git a/init/do_mounts.c b/init/do_mounts.c index c170d8b309b1..e7f0b0f18cce 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -629,19 +629,15 @@ static bool is_tmpfs; static struct dentry *rootfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - static unsigned long once; void *fill = ramfs_fill_super; - if (test_and_set_bit(0, &once)) - return ERR_PTR(-ENODEV); - if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs) fill = shmem_fill_super; return mount_nodev(fs_type, flags, data, fill); } -static struct file_system_type rootfs_fs_type = { +struct file_system_type rootfs_fs_type = { .name = "rootfs", .mount = rootfs_mount, .kill_sb = kill_litter_super, @@ -649,19 +645,12 @@ static struct file_system_type rootfs_fs_type = { int __init init_rootfs(void) { - int err = register_filesystem(&rootfs_fs_type); - - if (err) - return err; + int err = 0; if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] && (!root_fs_names || strstr(root_fs_names, "tmpfs"))) { err = shmem_init(); is_tmpfs = true; } - - if (err) - unregister_filesystem(&rootfs_fs_type); - return err; } -- cgit v1.2.3 From 33488845f211afcdb7e5c00a3152890e06cdc78e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 31 May 2019 20:09:15 -0400 Subject: constify ksys_mount() string arguments Signed-off-by: Al Viro --- drivers/base/devtmpfs.c | 3 +-- fs/namespace.c | 4 ++-- include/linux/syscalls.h | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 0dbc43068eeb..ba5c80903efe 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -357,8 +357,7 @@ int devtmpfs_mount(const char *mntdir) if (!thread) return 0; - err = ksys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, - NULL); + err = ksys_mount("devtmpfs", mntdir, "devtmpfs", MS_SILENT, NULL); if (err) printk(KERN_INFO "devtmpfs: error mounting %i\n", err); else diff --git a/fs/namespace.c b/fs/namespace.c index 2db2f4c36c50..e272c2403014 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3295,8 +3295,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name) } EXPORT_SYMBOL(mount_subtree); -int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type, - unsigned long flags, void __user *data) +int ksys_mount(const char __user *dev_name, const char __user *dir_name, + const char __user *type, unsigned long flags, void __user *data) { int ret; char *kernel_type; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index e2870fe1be5b..2a0ac10a6f95 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -1228,8 +1228,8 @@ asmlinkage long sys_ni_syscall(void); * the ksys_xyzyyz() functions prototyped below. */ -int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type, - unsigned long flags, void __user *data); +int ksys_mount(const char __user *dev_name, const char __user *dir_name, + const char __user *type, unsigned long flags, void __user *data); int ksys_umount(char __user *name, int flags); int ksys_dup(unsigned int fildes); int ksys_chroot(const char __user *filename); -- cgit v1.2.3 From 037f11b4752f717201143a1dc5d6acf3cb71ddfa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Jun 2019 18:09:44 -0400 Subject: mnt_init(): call shmem_init() unconditionally No point having two call sites (earlier in init_rootfs() from mnt_init() in case we are going to use shmem-style rootfs, later from do_basic_setup() unconditionally), along with the logics in shmem_init() itself to make the second call a no-op... Signed-off-by: Al Viro --- fs/namespace.c | 2 ++ include/linux/init.h | 2 +- init/do_mounts.c | 9 ++------- init/main.c | 1 - mm/shmem.c | 4 ---- 5 files changed, 5 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/namespace.c b/fs/namespace.c index e272c2403014..e6990f3d526d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "pnode.h" #include "internal.h" @@ -3740,6 +3741,7 @@ void __init mnt_init(void) fs_kobj = kobject_create_and_add("fs", NULL); if (!fs_kobj) printk(KERN_WARNING "%s: kobj create error\n", __func__); + shmem_init(); init_rootfs(); init_mount_tree(); } diff --git a/include/linux/init.h b/include/linux/init.h index cbe93521397e..212fc9e2f691 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -148,7 +148,7 @@ extern unsigned int reset_devices; /* used by init/main.c */ void setup_arch(char **); void prepare_namespace(void); -int __init init_rootfs(void); +void __init init_rootfs(void); extern struct file_system_type rootfs_fs_type; #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX) diff --git a/init/do_mounts.c b/init/do_mounts.c index e7f0b0f18cce..864c032e995d 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -643,14 +643,9 @@ struct file_system_type rootfs_fs_type = { .kill_sb = kill_litter_super, }; -int __init init_rootfs(void) +void __init init_rootfs(void) { - int err = 0; - if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] && - (!root_fs_names || strstr(root_fs_names, "tmpfs"))) { - err = shmem_init(); + (!root_fs_names || strstr(root_fs_names, "tmpfs"))) is_tmpfs = true; - } - return err; } diff --git a/init/main.c b/init/main.c index 5a2c69b4d7b3..4dbc7243557e 100644 --- a/init/main.c +++ b/init/main.c @@ -1000,7 +1000,6 @@ static void __init do_initcalls(void) static void __init do_basic_setup(void) { cpuset_init_smp(); - shmem_init(); driver_init(); init_irq_proc(); do_ctors(); diff --git a/mm/shmem.c b/mm/shmem.c index 1bb3b8dc8bb2..1f67ec9e2062 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3775,10 +3775,6 @@ int __init shmem_init(void) { int error; - /* If rootfs called this, don't re-init */ - if (shmem_inode_cachep) - return 0; - shmem_init_inodecache(); error = register_filesystem(&shmem_fs_type); -- cgit v1.2.3