From fb9273f2c10d100c0fa6544484bc806903d704da Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:56 +0100 Subject: [PATCH 01/63] drm: don't bother with super_operations and dentry_operations defaults will do just fine. Signed-off-by: Al Viro --- drivers/gpu/drm/drm_drv.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 862621494a93..8b44ac9a92ae 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -532,21 +532,13 @@ EXPORT_SYMBOL(drm_dev_unplug); static int drm_fs_cnt; static struct vfsmount *drm_fs_mnt; -static const struct dentry_operations drm_fs_dops = { - .d_dname = simple_dname, -}; - -static const struct super_operations drm_fs_sops = { - .statfs = simple_statfs, -}; - 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:", - &drm_fs_sops, - &drm_fs_dops, + NULL, + NULL, 0x010203ff); } From 619a6d167b29b0e39a049a989d4675d4596afe60 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:56 +0100 Subject: [PATCH 02/63] cxl: don't bother with dentry_operations default will do Signed-off-by: Al Viro --- drivers/misc/cxl/api.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 750470ef2049..a59c7af79873 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -37,14 +37,10 @@ static int cxl_fs_cnt; static struct vfsmount *cxl_vfs_mount; -static const struct dentry_operations cxl_fs_dops = { - .d_dname = simple_dname, -}; - 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, &cxl_fs_dops, + return mount_pseudo(fs_type, "cxl:", NULL, NULL, CXL_PSEUDO_FS_MAGIC); } From 8b1e058e0f529d6e097c35dfeb932bd10fc8e4fb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:56 +0100 Subject: [PATCH 03/63] cxlflash: don't bother with dentry_operations Signed-off-by: Al Viro --- drivers/scsi/cxlflash/ocxl_hw.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c index 37b8dc60f5f6..31cfdf2c8c30 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.c +++ b/drivers/scsi/cxlflash/ocxl_hw.c @@ -35,10 +35,6 @@ static int ocxlflash_fs_cnt; static struct vfsmount *ocxlflash_vfs_mount; -static const struct dentry_operations ocxlflash_fs_dops = { - .d_dname = simple_dname, -}; - /* * ocxlflash_fs_mount() - mount the pseudo-filesystem * @fs_type: File system type. @@ -52,7 +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, &ocxlflash_fs_dops, + return mount_pseudo(fs_type, "ocxlflash:", NULL, NULL, OCXLFLASH_FS_MAGIC); } From 985f4044871a5498206c4957c809c283ca84aca0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:56 +0100 Subject: [PATCH 04/63] balloon: don't bother with dentry_operations Signed-off-by: Al Viro --- drivers/virtio/virtio_balloon.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index f19061b585a4..554d1a98d193 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -761,11 +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) { - static const struct dentry_operations ops = { - .d_dname = simple_dname, - }; - - return mount_pseudo(fs_type, "balloon-kvm:", NULL, &ops, + return mount_pseudo(fs_type, "balloon-kvm:", NULL, NULL, BALLOON_KVM_MAGIC); } From 48b48750c3f9f91a4e340d0f796734ddd178ad9d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:57 +0100 Subject: [PATCH 05/63] zsmalloc: don't bother with dentry_operations Signed-off-by: Al Viro --- mm/zsmalloc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index 0787d33b80d8..d9f831f63625 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -1817,11 +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) { - static const struct dentry_operations ops = { - .d_dname = simple_dname, - }; - - return mount_pseudo(fs_type, "zsmalloc:", NULL, &ops, ZSMALLOC_MAGIC); + return mount_pseudo(fs_type, "zsmalloc:", NULL, NULL, ZSMALLOC_MAGIC); } static struct file_system_type zsmalloc_fs = { From 4de1e3a8ecec3432ed6ed7da0b90b34750358899 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 21 May 2019 08:22:17 +0100 Subject: [PATCH 06/63] z3fold: don't bother with dentry_operations Don't bother with dentry_operations as no dentry is ever allocated. Signed-off-by: David Howells --- mm/z3fold.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mm/z3fold.c b/mm/z3fold.c index 1ffecd6333e5..0b14daf930a8 100644 --- a/mm/z3fold.c +++ b/mm/z3fold.c @@ -242,11 +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) { - static const struct dentry_operations ops = { - .d_dname = simple_dname, - }; - - return mount_pseudo(fs_type, "z3fold:", NULL, &ops, 0x33); + return mount_pseudo(fs_type, "z3fold:", NULL, NULL, 0x33); } static struct file_system_type z3fold_fs = { From 7e5f7bb08b8cefd3a7e8961861f47fe1f0e830d4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:57 +0100 Subject: [PATCH 07/63] unexport simple_dname() Signed-off-by: Al Viro --- fs/d_path.c | 1 - fs/internal.h | 1 + include/linux/dcache.h | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) 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 diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f14e587c5d5d..361305ddd75e 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -291,7 +291,6 @@ static inline unsigned d_count(const struct dentry *dentry) */ extern __printf(4, 5) char *dynamic_dname(struct dentry *, char *, int, const char *, ...); -extern char *simple_dname(struct dentry *, char *, int); extern char *__d_path(const struct path *, const struct path *, char *, int); extern char *d_absolute_path(const struct path *, char *, int); From 1a6e9e76b713d9632783efe78295ed3507fdad64 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 20 May 2019 13:44:57 +0100 Subject: [PATCH 08/63] device-dax: Drop register_filesystem() The device-dax fs is only there to allocate a common inode for each device-node that refers to the same device by major:minor. It is otherwise not user mountable and need not be displayed in /proc/filesystems. Reported-by: Al Viro Acked-by: Al Viro Signed-off-by: Dan Williams Signed-off-by: Al Viro --- drivers/dax/super.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index bbd57ca0634a..35f051efaf35 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -630,10 +630,6 @@ static int dax_fs_init(void) if (!dax_cache) return -ENOMEM; - rc = register_filesystem(&dax_fs_type); - if (rc) - goto err_register_fs; - dax_mnt = kern_mount(&dax_fs_type); if (IS_ERR(dax_mnt)) { rc = PTR_ERR(dax_mnt); @@ -644,8 +640,6 @@ static int dax_fs_init(void) return 0; err_mount: - unregister_filesystem(&dax_fs_type); - err_register_fs: kmem_cache_destroy(dax_cache); return rc; @@ -654,7 +648,6 @@ static int dax_fs_init(void) static void dax_fs_exit(void) { kern_unmount(dax_mnt); - unregister_filesystem(&dax_fs_type); kmem_cache_destroy(dax_cache); } From 1f58bb18f6f28d1df0b7144d90bc90ee5672416d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 May 2019 13:44:57 +0100 Subject: [PATCH 09/63] 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(-) 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); } From f7a9945184100b531f0de3b12c617a349236dd8a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 12:42:58 -0400 Subject: [PATCH 10/63] 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(-) 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; From feb8ae43a7b33148028829b1b1691b28c874c952 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 13:18:42 -0400 Subject: [PATCH 11/63] 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(-) 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)) From 0ce0cf12fc4c6a089717ff613d76457052cf4303 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 15:42:48 -0400 Subject: [PATCH 12/63] 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(-) 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) { From b9662f3103546005b9cc01862bb1031fe5e99ff9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:28 +0000 Subject: [PATCH 13/63] vfs: Convert rpc_pipefs to use the new mount API Convert the rpc_pipefs 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: Trond Myklebust cc: Anna Schumaker cc: "J. Bruce Fields" cc: Jeff Layton cc: linux-nfs@vger.kernel.org --- net/sunrpc/rpc_pipe.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 979d23646e33..0b6c27cd6bde 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1347,11 +1348,11 @@ rpc_gssd_dummy_depopulate(struct dentry *pipe_dentry) } static int -rpc_fill_super(struct super_block *sb, void *data, int silent) +rpc_fill_super(struct super_block *sb, struct fs_context *fc) { struct inode *inode; struct dentry *root, *gssd_dentry; - struct net *net = get_net(sb->s_fs_info); + struct net *net = sb->s_fs_info; struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); int err; @@ -1408,12 +1409,29 @@ gssd_running(struct net *net) } EXPORT_SYMBOL_GPL(gssd_running); -static struct dentry * -rpc_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int rpc_fs_get_tree(struct fs_context *fc) { - struct net *net = current->nsproxy->net_ns; - return mount_ns(fs_type, flags, data, net, net->user_ns, rpc_fill_super); + fc->s_fs_info = get_net(fc->net_ns); + return vfs_get_super(fc, vfs_get_keyed_super, rpc_fill_super); +} + +static void rpc_fs_free_fc(struct fs_context *fc) +{ + if (fc->s_fs_info) + put_net(fc->s_fs_info); +} + +static const struct fs_context_operations rpc_fs_context_ops = { + .free = rpc_fs_free_fc, + .get_tree = rpc_fs_get_tree, +}; + +static int rpc_init_fs_context(struct fs_context *fc) +{ + put_user_ns(fc->user_ns); + fc->user_ns = get_user_ns(fc->net_ns->user_ns); + fc->ops = &rpc_fs_context_ops; + return 0; } static void rpc_kill_sb(struct super_block *sb) @@ -1441,7 +1459,7 @@ static void rpc_kill_sb(struct super_block *sb) static struct file_system_type rpc_pipe_fs_type = { .owner = THIS_MODULE, .name = "rpc_pipefs", - .mount = rpc_mount, + .init_fs_context = rpc_init_fs_context, .kill_sb = rpc_kill_sb, }; MODULE_ALIAS_FS("rpc_pipefs"); From 96a374a35f822e53cad3b011dd5fbadec1b1473f Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:27 +0000 Subject: [PATCH 14/63] 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(-) 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) { - struct net *net = current->nsproxy->net_ns; - return mount_ns(fs_type, flags, data, net, net->user_ns, nfsd_fill_super); + 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) +{ + 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"); From bb7b6b2bbdb827e68cd506c8f5e3ba13215cccb2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:28 +0000 Subject: [PATCH 15/63] 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(-) 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, From 2527b284defaeadf74829b0b0bd3207ca7f165eb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 17:09:01 -0400 Subject: [PATCH 16/63] 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(-) 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) { From fd912087f4a897cfdf8274f8085c501742638be2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 17:23:30 -0400 Subject: [PATCH 17/63] 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(-) 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; } From 20284ab7427ffac514faf44fd9eb50e5745f4474 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 17:31:45 -0400 Subject: [PATCH 18/63] 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(-) 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); } From 709a643da8b8c5fc823e1870d8227ca0eeb51311 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 17:46:05 -0400 Subject: [PATCH 19/63] mqueue: set ->user_ns before ->get_tree() ... so that we could lift the capability checks into ->get_tree() caller Signed-off-by: Al Viro --- ipc/mqueue.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 216cad1ff0d0..9f8e4cbcec00 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -364,8 +364,6 @@ static int mqueue_get_tree(struct fs_context *fc) { struct mqueue_fs_context *ctx = fc->fs_private; - put_user_ns(fc->user_ns); - fc->user_ns = get_user_ns(ctx->ipc_ns->user_ns); fc->s_fs_info = ctx->ipc_ns; return vfs_get_super(fc, vfs_get_keyed_super, mqueue_fill_super); } @@ -374,8 +372,7 @@ static void mqueue_fs_context_free(struct fs_context *fc) { struct mqueue_fs_context *ctx = fc->fs_private; - if (ctx->ipc_ns) - put_ipc_ns(ctx->ipc_ns); + put_ipc_ns(ctx->ipc_ns); kfree(ctx); } @@ -388,6 +385,8 @@ static int mqueue_init_fs_context(struct fs_context *fc) return -ENOMEM; ctx->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns); + put_user_ns(fc->user_ns); + fc->user_ns = get_user_ns(ctx->ipc_ns->user_ns); fc->fs_private = ctx; fc->ops = &mqueue_fs_context_ops; return 0; @@ -406,6 +405,8 @@ static struct vfsmount *mq_create_mount(struct ipc_namespace *ns) ctx = fc->fs_private; put_ipc_ns(ctx->ipc_ns); ctx->ipc_ns = get_ipc_ns(ns); + put_user_ns(fc->user_ns); + fc->user_ns = get_user_ns(ctx->ipc_ns->user_ns); mnt = fc_mount(fc); put_fs_context(fc); From 46cf047a945c7a53cb2dc9353a87a9a4e3e778cd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 18:10:24 -0400 Subject: [PATCH 20/63] 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(-) 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; From d5f68d330c156774bf69059e434b5d8acea3b92e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 13 May 2019 12:33:22 -0400 Subject: [PATCH 21/63] cpuset: move mount -t cpuset logics into cgroup.c ... and get rid of the weird dances in ->get_tree() - that logics can be easily handled in ->init_fs_context(). Signed-off-by: Al Viro --- kernel/cgroup/cgroup.c | 47 ++++++++++++++++++++++++++++++++ kernel/cgroup/cpuset.c | 61 +----------------------------------------- 2 files changed, 48 insertions(+), 60 deletions(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index bbcdd3457eb0..4a0eb465d17e 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -2225,6 +2225,50 @@ static struct file_system_type cgroup2_fs_type = { .fs_flags = FS_USERNS_MOUNT, }; +#ifdef CONFIG_CPUSETS +static const struct fs_context_operations cpuset_fs_context_ops = { + .get_tree = cgroup1_get_tree, + .free = cgroup_fs_context_free, +}; + +/* + * This is ugly, but preserves the userspace API for existing cpuset + * users. If someone tries to mount the "cpuset" filesystem, we + * silently switch it to mount "cgroup" instead + */ +static int cpuset_init_fs_context(struct fs_context *fc) +{ + char *agent = kstrdup("/sbin/cpuset_release_agent", GFP_USER); + struct cgroup_fs_context *ctx; + int err; + + err = cgroup_init_fs_context(fc); + if (err) { + kfree(agent); + return err; + } + + fc->ops = &cpuset_fs_context_ops; + + ctx = cgroup_fc2context(fc); + ctx->subsys_mask = 1 << cpuset_cgrp_id; + ctx->flags |= CGRP_ROOT_NOPREFIX; + ctx->release_agent = agent; + + get_filesystem(&cgroup_fs_type); + put_filesystem(fc->fs_type); + fc->fs_type = &cgroup_fs_type; + + return 0; +} + +static struct file_system_type cpuset_fs_type = { + .name = "cpuset", + .init_fs_context = cpuset_init_fs_context, + .fs_flags = FS_USERNS_MOUNT, +}; +#endif + int cgroup_path_ns_locked(struct cgroup *cgrp, char *buf, size_t buflen, struct cgroup_namespace *ns) { @@ -5710,6 +5754,9 @@ int __init cgroup_init(void) WARN_ON(register_filesystem(&cgroup_fs_type)); WARN_ON(register_filesystem(&cgroup2_fs_type)); WARN_ON(!proc_create_single("cgroups", 0, NULL, proc_cgroupstats_show)); +#ifdef CONFIG_CPUSETS + WARN_ON(register_filesystem(&cpuset_fs_type)); +#endif return 0; } diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 6a1942ed781c..9806c8c8b509 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -355,59 +355,6 @@ static inline bool is_in_v2_mode(void) (cpuset_cgrp_subsys.root->flags & CGRP_ROOT_CPUSET_V2_MODE); } -/* - * This is ugly, but preserves the userspace API for existing cpuset - * users. If someone tries to mount the "cpuset" filesystem, we - * silently switch it to mount "cgroup" instead - */ -static int cpuset_get_tree(struct fs_context *fc) -{ - struct file_system_type *cgroup_fs; - struct fs_context *new_fc; - int ret; - - cgroup_fs = get_fs_type("cgroup"); - if (!cgroup_fs) - return -ENODEV; - - new_fc = fs_context_for_mount(cgroup_fs, fc->sb_flags); - if (IS_ERR(new_fc)) { - ret = PTR_ERR(new_fc); - } else { - static const char agent_path[] = "/sbin/cpuset_release_agent"; - ret = vfs_parse_fs_string(new_fc, "cpuset", NULL, 0); - if (!ret) - ret = vfs_parse_fs_string(new_fc, "noprefix", NULL, 0); - if (!ret) - ret = vfs_parse_fs_string(new_fc, "release_agent", - agent_path, sizeof(agent_path) - 1); - if (!ret) - ret = vfs_get_tree(new_fc); - if (!ret) { /* steal the result */ - fc->root = new_fc->root; - new_fc->root = NULL; - } - put_fs_context(new_fc); - } - put_filesystem(cgroup_fs); - return ret; -} - -static const struct fs_context_operations cpuset_fs_context_ops = { - .get_tree = cpuset_get_tree, -}; - -static int cpuset_init_fs_context(struct fs_context *fc) -{ - fc->ops = &cpuset_fs_context_ops; - return 0; -} - -static struct file_system_type cpuset_fs_type = { - .name = "cpuset", - .init_fs_context = cpuset_init_fs_context, -}; - /* * Return in pmask the portion of a cpusets's cpus_allowed that * are online. If none are online, walk up the cpuset hierarchy @@ -2853,13 +2800,11 @@ struct cgroup_subsys cpuset_cgrp_subsys = { /** * cpuset_init - initialize cpusets at system boot * - * Description: Initialize top_cpuset and the cpuset internal file system, + * Description: Initialize top_cpuset **/ int __init cpuset_init(void) { - int err = 0; - BUG_ON(!alloc_cpumask_var(&top_cpuset.cpus_allowed, GFP_KERNEL)); BUG_ON(!alloc_cpumask_var(&top_cpuset.effective_cpus, GFP_KERNEL)); BUG_ON(!zalloc_cpumask_var(&top_cpuset.subparts_cpus, GFP_KERNEL)); @@ -2873,10 +2818,6 @@ int __init cpuset_init(void) set_bit(CS_SCHED_LOAD_BALANCE, &top_cpuset.flags); top_cpuset.relax_domain_level = -1; - err = register_filesystem(&cpuset_fs_type); - if (err < 0) - return err; - BUG_ON(!alloc_cpumask_var(&cpus_attach, GFP_KERNEL)); return 0; From 059338aae33165179352a26b58d815801072c87d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 May 2019 18:16:04 -0400 Subject: [PATCH 22/63] 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(-) 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. */ From c3aabf0780a506225b53bfe2b5177dd5dfec093d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 13 May 2019 12:57:22 -0400 Subject: [PATCH 23/63] 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(-) 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. */ From 7cdfa44227b0d8842d46a775cebe4311150cb8f2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:22 +0000 Subject: [PATCH 24/63] 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(+) 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); From c80fa7c8301c10ad10d997b9e86b4aeac5923b3e Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 25/63] 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(+) 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 @@ struct super_block *sget_fc(struct fs_context *fc, } 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 */ From 31d6d5ce53400d6dc58e29ddd8dc184b3ba89d66 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 26/63] 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 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 From 52db59df17c0cd3ee4071a75a8509287a662abac Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 27/63] 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(-) 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); From 33cada40b51f083d8508e66f96c646640f773835 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 28/63] 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(-) 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, }; From 9030d16eb8adcbf9e80d20b909856c6fdabfdec4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 29/63] 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(-) 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, }; From 059b20d9da69d3a9bfb7ab00d1e5a3114a31c822 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 30/63] 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(-) 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, }; From 4fa7ec5db7e731a3db26b9647f39b0595f74347d Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 31/63] 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(-) 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, }; From 8e9231f819e32d8efb53b0f17f293bab74bed8ce Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:23 +0000 Subject: [PATCH 32/63] vfs: Convert zsmalloc to use the new mount API Convert the zsmalloc 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: Minchan Kim cc: Nitin Gupta cc: Sergey Senozhatsky cc: linux-mm@kvack.org Signed-off-by: Al Viro --- mm/zsmalloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index ef230be8c03e..910d0407f8f1 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -1814,15 +1815,14 @@ static void lock_zspage(struct zspage *zspage) } while ((page = get_next_page(page)) != NULL); } -static struct dentry *zs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int zs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, NULL, ZSMALLOC_MAGIC); + return init_pseudo(fc, ZSMALLOC_MAGIC) ? 0 : -ENOMEM; } static struct file_system_type zsmalloc_fs = { .name = "zsmalloc", - .mount = zs_mount, + .init_fs_context = zs_init_fs_context, .kill_sb = kill_anon_super, }; From ea8157ab2ae5e914dd427e5cfab533b6da3819cd Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 21 May 2019 07:55:45 +0100 Subject: [PATCH 33/63] zsfold: Convert zsfold to use the new mount API Convert the zsfold 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 --- include/uapi/linux/magic.h | 1 + mm/z3fold.c | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index f8c00045d537..85c1119d0b0b 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -91,5 +91,6 @@ #define UDF_SUPER_MAGIC 0x15013346 #define BALLOON_KVM_MAGIC 0x13661366 #define ZSMALLOC_MAGIC 0x58295829 +#define Z3FOLD_MAGIC 0x33 #endif /* __LINUX_MAGIC_H__ */ diff --git a/mm/z3fold.c b/mm/z3fold.c index abeb5bcbea57..a43e8bfcaaea 100644 --- a/mm/z3fold.c +++ b/mm/z3fold.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -35,12 +34,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include /* * NCHUNKS_ORDER determines the internal allocation granularity, effectively @@ -239,15 +240,14 @@ 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) +static int z3fold_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, NULL, 0x33); + return init_pseudo(fc, Z3FOLD_MAGIC) ? 0 : -ENOMEM; } static struct file_system_type z3fold_fs = { .name = "z3fold", - .mount = z3fold_do_mount, + .init_fs_context = z3fold_init_fs_context, .kill_sb = kill_anon_super, }; From fba9be49701a8e89a691beffb11bfa97df8f0c9f Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:24 +0000 Subject: [PATCH 34/63] vfs: Convert sockfs to use the new mount API Convert the sockfs 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: netdev@vger.kernel.org Signed-off-by: Al Viro --- net/socket.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/net/socket.c b/net/socket.c index c86679584eed..5061c5d2730c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -359,19 +360,22 @@ static const struct xattr_handler *sockfs_xattr_handlers[] = { NULL }; -static struct dentry *sockfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sockfs_init_fs_context(struct fs_context *fc) { - return mount_pseudo_xattr(fs_type, &sockfs_ops, - sockfs_xattr_handlers, - &sockfs_dentry_operations, SOCKFS_MAGIC); + struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC); + if (!ctx) + return -ENOMEM; + ctx->ops = &sockfs_ops; + ctx->dops = &sockfs_dentry_operations; + ctx->xattr = sockfs_xattr_handlers; + return 0; } static struct vfsmount *sock_mnt __read_mostly; static struct file_system_type sock_fs_type = { .name = "sockfs", - .mount = sockfs_mount, + .init_fs_context = sockfs_init_fs_context, .kill_sb = kill_anon_super, }; From 75d4e06f049ffb059fdf7e81c0c4c9fab2ba60e4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:24 +0000 Subject: [PATCH 35/63] vfs: Convert dax to use the new mount API Convert the dax 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: Dan Williams cc: Vishal Verma cc: Keith Busch cc: Dave Jiang cc: linux-nvdimm@lists.01.org Signed-off-by: Al Viro --- drivers/dax/super.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index f83814eea5ad..a93225c0a623 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -437,16 +438,19 @@ static const struct super_operations dax_sops = { .drop_inode = generic_delete_inode, }; -static struct dentry *dax_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int dax_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, &dax_sops, NULL, DAXFS_MAGIC); + struct pseudo_fs_context *ctx = init_pseudo(fc, DAXFS_MAGIC); + if (!ctx) + return -ENOMEM; + ctx->ops = &dax_sops; + return 0; } static struct file_system_type dax_fs_type = { - .name = "dax", - .mount = dax_mount, - .kill_sb = kill_anon_super, + .name = "dax", + .init_fs_context = dax_init_fs_context, + .kill_sb = kill_anon_super, }; static int dax_test(struct inode *inode, void *data) From 4a457910a8d77a2142098c1b694da33b8fc16c8a Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:24 +0000 Subject: [PATCH 36/63] vfs: Convert drm to use the new mount API Convert the drm 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: Daniel Vetter cc: David Airlie cc: dri-devel@lists.freedesktop.org Signed-off-by: Al Viro --- drivers/gpu/drm/drm_drv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 48365c62a190..f23eb993c4fa 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -532,16 +533,15 @@ EXPORT_SYMBOL(drm_dev_unplug); static int drm_fs_cnt; 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) +static int drm_fs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, NULL, 0x010203ff); + return init_pseudo(fc, 0x010203ff) ? 0 : -ENOMEM; } static struct file_system_type drm_fs_type = { .name = "drm", .owner = THIS_MODULE, - .mount = drm_fs_mount, + .init_fs_context = drm_fs_init_fs_context, .kill_sb = kill_anon_super, }; From b06f973fe713f6d89addaa4b8fc5897612e5fefb Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:24 +0000 Subject: [PATCH 37/63] vfs: Convert ia64 perfmon to use the new mount API Convert the ia64 perfmon 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: Tony Luck cc: Fenghua Yu cc: linux-ia64@vger.kernel.org Signed-off-by: Al Viro --- arch/ia64/kernel/perfmon.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index a30da6f2c28e..a41299010b5e 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -599,17 +600,19 @@ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) /* forward declaration */ 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) +static int pfmfs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, &pfmfs_dentry_operations, - PFMFS_MAGIC); + struct pseudo_fs_context *ctx = init_pseudo(fc, PFMFS_MAGIC); + if (!ctx) + return -ENOMEM; + ctx->dops = &pfmfs_dentry_operations; + return 0; } static struct file_system_type pfm_fs_type = { - .name = "pfmfs", - .mount = pfmfs_mount, - .kill_sb = kill_anon_super, + .name = "pfmfs", + .init_fs_context = pfmfs_init_fs_context, + .kill_sb = kill_anon_super, }; MODULE_ALIAS_FS("pfmfs"); From 52418c8f0073d6641411caf0a24740ed58436b21 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:24 +0000 Subject: [PATCH 38/63] vfs: Convert cxl to use the new mount API Convert the cxl 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: Andrew Donnellan Acked-by: Frederic Barrat cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Al Viro --- drivers/misc/cxl/api.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 1f2b0535a8cf..d69594475ac9 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -37,16 +38,15 @@ static int cxl_fs_cnt; 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) +static int cxl_fs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, NULL, CXL_PSEUDO_FS_MAGIC); + return init_pseudo(fc, CXL_PSEUDO_FS_MAGIC) ? 0 : -ENOMEM; } static struct file_system_type cxl_fs_type = { .name = "cxl", .owner = THIS_MODULE, - .mount = cxl_fs_mount, + .init_fs_context = cxl_fs_init_fs_context, .kill_sb = kill_anon_super, }; From 219e69639070438c969e7da282f513595b00f9d8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:25 +0000 Subject: [PATCH 39/63] vfs: Convert ocxlflash to use the new mount API Convert the ocxlflash 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: Matthew R. Ochs cc: "Manoj N. Kumar" cc: Uma Krishnan cc: "James E.J. Bottomley" cc: "Martin K. Petersen" cc: linux-scsi@vger.kernel.org Signed-off-by: Al Viro --- drivers/scsi/cxlflash/ocxl_hw.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c index 38e1fbd2b406..e5af37ee9b6e 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.c +++ b/drivers/scsi/cxlflash/ocxl_hw.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -35,26 +36,15 @@ static int ocxlflash_fs_cnt; static struct vfsmount *ocxlflash_vfs_mount; -/* - * ocxlflash_fs_mount() - mount the pseudo-filesystem - * @fs_type: File system type. - * @flags: Flags for the filesystem. - * @dev_name: Device name associated with the filesystem. - * @data: Data pointer. - * - * Return: pointer to the directory entry structure - */ -static struct dentry *ocxlflash_fs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int ocxlflash_fs_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, NULL, OCXLFLASH_FS_MAGIC); + return init_pseudo(fc, OCXLFLASH_FS_MAGIC) ? 0 : -ENOMEM; } static struct file_system_type ocxlflash_fs_type = { .name = "ocxlflash", .owner = THIS_MODULE, - .mount = ocxlflash_fs_mount, + .init_fs_context = ocxlflash_fs_init_fs_context, .kill_sb = kill_anon_super, }; From 99558d203ceab980d74066daac4050609f5eccf4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:25 +0000 Subject: [PATCH 40/63] vfs: Convert virtio_balloon to use the new mount API Convert the virtio_balloon 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: "Michael S. Tsirkin" cc: Jason Wang cc: virtualization@lists.linux-foundation.org Signed-off-by: Al Viro --- drivers/virtio/virtio_balloon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 62bafc4f2662..4ca2d71d43f8 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -31,6 +31,7 @@ #include #include #include +#include /* * Balloon device works in 4K page units. So each page is pointed to by @@ -758,15 +759,14 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, return MIGRATEPAGE_SUCCESS; } -static struct dentry *balloon_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int balloon_init_fs_context(struct fs_context *fc) { - return mount_pseudo(fs_type, NULL, NULL, BALLOON_KVM_MAGIC); + return init_pseudo(fc, BALLOON_KVM_MAGIC) ? 0 : -ENOMEM; } static struct file_system_type balloon_fs = { .name = "balloon-kvm", - .mount = balloon_mount, + .init_fs_context = balloon_init_fs_context, .kill_sb = kill_anon_super, }; From 389e22fb46eb1f48b089060c30030790e7a41033 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:25 +0000 Subject: [PATCH 41/63] 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(-) 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, }; From 8d9e46d80777b484f8f0945c317ad618224d7811 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 11 May 2019 11:43:59 -0400 Subject: [PATCH 42/63] 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(-) 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) \ From db2c246a091efe2e49aeb3fe0cf6ed2affbddf37 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:26 +0000 Subject: [PATCH 43/63] 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(-) 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; } From 023d066a0d0a87696c04b0de2ceae53063d0b655 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:28 +0000 Subject: [PATCH 44/63] 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(-) 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 @@ struct super_block *sget_fc(struct fs_context *fc, 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 @@ struct super_block *sget_userns(struct file_system_type *type, 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 *), From 2ac295d4f0c095310addbcb03d91d2a4c9f7d435 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Jun 2019 20:48:55 -0400 Subject: [PATCH 45/63] 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(-) 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; From c23a0bbab30cc1714b6b1d6a1c153a5ccab3f0d8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 22 May 2019 21:23:39 -0400 Subject: [PATCH 46/63] 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(-) 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; From bc99a664e9be24e49e09da1250ede0c598d958d1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:28 +0000 Subject: [PATCH 47/63] 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(-) 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"); From 6bc62f2067d30f90621c42a2794c2515eff7bf11 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:29 +0000 Subject: [PATCH 48/63] 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(-) 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"); From 4799974555de565df0d0aca86c15bbea70105a19 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:29 +0000 Subject: [PATCH 49/63] 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(-) 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 mount_single(fs_type, flags, data, efivarfs_fill_super); + 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) +{ + 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, }; From 7515c22cc8c80b241b7317fb17d853691dab0221 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:29 +0000 Subject: [PATCH 50/63] vfs: Convert qib_fs/ipathfs to use the new mount API Convert the qib_fs/ipathfs 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. [Q] Can qib_remove() race with qibfs_kill_super()? Should qib_super accesses be serialised with some sort of lock? [A] yes, it can and no, that's not the right solution. See vfs.git #qibfs for an old attempt to handle that cleanly. Infiniband folks were not interested... Signed-off-by: David Howells Reviewed-by: Dennis Dalessandro cc: Mike Marciniszyn cc: linux-rdma@vger.kernel.org Signed-off-by: Al Viro --- drivers/infiniband/hw/qib/qib_fs.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index ceb42d948412..41a569558a15 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -506,7 +507,7 @@ static int remove_device_files(struct super_block *sb, * after device init. The direct add_cntr_files() call handles adding * them from the init code, when the fs is already mounted. */ -static int qibfs_fill_super(struct super_block *sb, void *data, int silent) +static int qibfs_fill_super(struct super_block *sb, struct fs_context *fc) { struct qib_devdata *dd; unsigned long index; @@ -534,17 +535,24 @@ static int qibfs_fill_super(struct super_block *sb, void *data, int silent) return ret; } -static struct dentry *qibfs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int qibfs_get_tree(struct fs_context *fc) { - struct dentry *ret; - - ret = mount_single(fs_type, flags, data, qibfs_fill_super); - if (!IS_ERR(ret)) - qib_super = ret->d_sb; + int ret = get_tree_single(fc, qibfs_fill_super); + if (ret == 0) + qib_super = fc->root->d_sb; return ret; } +static const struct fs_context_operations qibfs_context_ops = { + .get_tree = qibfs_get_tree, +}; + +static int qibfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &qibfs_context_ops; + return 0; +} + static void qibfs_kill_super(struct super_block *s) { kill_litter_super(s); @@ -583,7 +591,7 @@ int qibfs_remove(struct qib_devdata *dd) static struct file_system_type qibfs_fs_type = { .owner = THIS_MODULE, .name = "ipathfs", - .mount = qibfs_mount, + .init_fs_context = qibfs_init_fs_context, .kill_sb = qibfs_kill_super, }; MODULE_ALIAS_FS("ipathfs"); From 129f809d2aa9c02cd1ab9714b265d828db3691ec Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:29 +0000 Subject: [PATCH 51/63] vfs: Convert ibmasmfs to use the new mount API Convert the ibmasmfs 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: Arnd Bergmann cc: Greg Kroah-Hartman Signed-off-by: Al Viro --- drivers/misc/ibmasm/ibmasmfs.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index fa840666bdd1..4eb844124bc0 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -74,6 +74,7 @@ */ #include +#include #include #include #include @@ -88,13 +89,21 @@ static LIST_HEAD(service_processors); static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode); static void ibmasmfs_create_files (struct super_block *sb); -static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent); +static int ibmasmfs_fill_super(struct super_block *sb, struct fs_context *fc); - -static struct dentry *ibmasmfs_mount(struct file_system_type *fst, - int flags, const char *name, void *data) +static int ibmasmfs_get_tree(struct fs_context *fc) { - return mount_single(fst, flags, data, ibmasmfs_fill_super); + return get_tree_single(fc, ibmasmfs_fill_super); +} + +static const struct fs_context_operations ibmasmfs_context_ops = { + .get_tree = ibmasmfs_get_tree, +}; + +static int ibmasmfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &ibmasmfs_context_ops; + return 0; } static const struct super_operations ibmasmfs_s_ops = { @@ -107,12 +116,12 @@ static const struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations; static struct file_system_type ibmasmfs_type = { .owner = THIS_MODULE, .name = "ibmasmfs", - .mount = ibmasmfs_mount, + .init_fs_context = ibmasmfs_init_fs_context, .kill_sb = kill_litter_super, }; MODULE_ALIAS_FS("ibmasmfs"); -static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent) +static int ibmasmfs_fill_super(struct super_block *sb, struct fs_context *fc) { struct inode *root; From c6a2c720d206d37e67e533af898c45d62fb07505 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: [PATCH 52/63] vfs: Convert oprofilefs to use the new mount API Convert the oprofilefs 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: Robert Richter cc: oprofile-list@lists.sf.net Signed-off-by: Al Viro --- drivers/oprofile/oprofilefs.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index 4ea08979312c..0875f2f122b3 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -238,7 +239,7 @@ struct dentry *oprofilefs_mkdir(struct dentry *parent, char const *name) } -static int oprofilefs_fill_super(struct super_block *sb, void *data, int silent) +static int oprofilefs_fill_super(struct super_block *sb, struct fs_context *fc) { struct inode *root_inode; @@ -263,18 +264,25 @@ static int oprofilefs_fill_super(struct super_block *sb, void *data, int silent) return 0; } - -static struct dentry *oprofilefs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int oprofilefs_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, oprofilefs_fill_super); + return get_tree_single(fc, oprofilefs_fill_super); } +static const struct fs_context_operations oprofilefs_context_ops = { + .get_tree = oprofilefs_get_tree, +}; + +static int oprofilefs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &oprofilefs_context_ops; + return 0; +} static struct file_system_type oprofilefs_type = { .owner = THIS_MODULE, .name = "oprofilefs", - .mount = oprofilefs_mount, + .init_fs_context = oprofilefs_init_fs_context, .kill_sb = kill_litter_super, }; MODULE_ALIAS_FS("oprofilefs"); From e5d82a7360d124ae1a38c2a5eac92ba49b125191 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: [PATCH 53/63] vfs: Convert gadgetfs to use the new mount API Convert the gadgetfs 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: Felipe Balbi cc: linux-usb@vger.kernel.org Signed-off-by: Al Viro --- drivers/usb/gadget/legacy/inode.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 249277d0e53f..b47938dff1a2 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1990,7 +1991,7 @@ static const struct super_operations gadget_fs_operations = { }; static int -gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) +gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc) { struct inode *inode; struct dev_data *dev; @@ -2044,11 +2045,19 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) } /* "mount -t gadgetfs path /dev/gadget" ends up here */ -static struct dentry * -gadgetfs_mount (struct file_system_type *t, int flags, - const char *path, void *opts) +static int gadgetfs_get_tree(struct fs_context *fc) { - return mount_single (t, flags, opts, gadgetfs_fill_super); + return get_tree_single(fc, gadgetfs_fill_super); +} + +static const struct fs_context_operations gadgetfs_context_ops = { + .get_tree = gadgetfs_get_tree, +}; + +static int gadgetfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &gadgetfs_context_ops; + return 0; } static void @@ -2068,7 +2077,7 @@ gadgetfs_kill_sb (struct super_block *sb) static struct file_system_type gadgetfs_type = { .owner = THIS_MODULE, .name = shortname, - .mount = gadgetfs_mount, + .init_fs_context = gadgetfs_init_fs_context, .kill_sb = gadgetfs_kill_sb, }; MODULE_ALIAS_FS("gadgetfs"); From 2345771f87dfd53c1c38a64be1638658ef31f460 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: [PATCH 54/63] vfs: Convert xenfs to use the new mount API Convert the xenfs 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 Reviewed-by: Juergen Gross cc: Boris Ostrovsky cc: Stefano Stabellini cc: xen-devel@lists.xenproject.org Signed-off-by: Al Viro --- drivers/xen/xenfs/super.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c index 71ddfb4cf61c..bb1f88c1e72b 100644 --- a/drivers/xen/xenfs/super.c +++ b/drivers/xen/xenfs/super.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,7 @@ static const struct file_operations capabilities_file_ops = { .llseek = default_llseek, }; -static int xenfs_fill_super(struct super_block *sb, void *data, int silent) +static int xenfs_fill_super(struct super_block *sb, struct fs_context *fc) { static const struct tree_descr xenfs_files[] = { [2] = { "xenbus", &xen_xenbus_fops, S_IRUSR|S_IWUSR }, @@ -67,17 +68,25 @@ static int xenfs_fill_super(struct super_block *sb, void *data, int silent) xen_initial_domain() ? xenfs_init_files : xenfs_files); } -static struct dentry *xenfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int xenfs_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, xenfs_fill_super); + return get_tree_single(fc, xenfs_fill_super); +} + +static const struct fs_context_operations xenfs_context_ops = { + .get_tree = xenfs_get_tree, +}; + +static int xenfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &xenfs_context_ops; + return 0; } static struct file_system_type xenfs_type = { .owner = THIS_MODULE, .name = "xenfs", - .mount = xenfs_mount, + .init_fs_context = xenfs_init_fs_context, .kill_sb = kill_litter_super, }; MODULE_ALIAS_FS("xenfs"); From 7ab2fa7693c3f0ce8445fd4e9e4e58e34e6a2213 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: [PATCH 55/63] 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(-) 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 @@ static int openprom_fill_super(struct super_block *s, void *data, int silent) 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"); From b0ecc9da5ff64b59c810d1e9c82d06488805da77 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: [PATCH 56/63] vfs: Convert apparmorfs to use the new mount API Convert the apparmorfs 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: John Johansen cc: apparmor@lists.ubuntu.com cc: linux-security-module@vger.kernel.org Signed-off-by: Al Viro --- security/apparmor/apparmorfs.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 9ab5613fe07c..5131bd90309d 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -136,7 +137,7 @@ static const struct super_operations aafs_super_ops = { .show_path = aafs_show_path, }; -static int fill_super(struct super_block *sb, void *data, int silent) +static int apparmorfs_fill_super(struct super_block *sb, struct fs_context *fc) { static struct tree_descr files[] = { {""} }; int error; @@ -149,16 +150,25 @@ static int fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct dentry *aafs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int apparmorfs_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, fill_super); + return get_tree_single(fc, apparmorfs_fill_super); +} + +static const struct fs_context_operations apparmorfs_context_ops = { + .get_tree = apparmorfs_get_tree, +}; + +static int apparmorfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &apparmorfs_context_ops; + return 0; } static struct file_system_type aafs_ops = { .owner = THIS_MODULE, .name = AAFS_NAME, - .mount = aafs_mount, + .init_fs_context = apparmorfs_init_fs_context, .kill_sb = kill_anon_super, }; From 5c86d7e0433acb6f5d5f3cc2adf8ea3f6bc6bbda Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: [PATCH 57/63] vfs: Convert securityfs to use the new mount API Convert the securityfs 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-security-module@vger.kernel.org Signed-off-by: Al Viro --- security/inode.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/security/inode.c b/security/inode.c index aacc4dabba7d..70f00064016d 100644 --- a/security/inode.c +++ b/security/inode.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,7 @@ static const struct super_operations securityfs_super_operations = { .free_inode = securityfs_free_inode, }; -static int fill_super(struct super_block *sb, void *data, int silent) +static int securityfs_fill_super(struct super_block *sb, struct fs_context *fc) { static const struct tree_descr files[] = {{""}}; int error; @@ -53,17 +54,25 @@ static int fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct dentry *get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int securityfs_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, fill_super); + return get_tree_single(fc, securityfs_fill_super); +} + +static const struct fs_context_operations securityfs_context_ops = { + .get_tree = securityfs_get_tree, +}; + +static int securityfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &securityfs_context_ops; + return 0; } static struct file_system_type fs_type = { .owner = THIS_MODULE, .name = "securityfs", - .mount = get_sb, + .init_fs_context = securityfs_init_fs_context, .kill_sb = kill_litter_super, }; From 920f50b2a44bbc5e332a3f84f7ad4040ee62fcc6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:30 +0000 Subject: [PATCH 58/63] vfs: Convert selinuxfs to use the new mount API Convert the selinuxfs 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: Paul Moore cc: Stephen Smalley cc: Eric Paris cc: selinux@vger.kernel.org cc: linux-security-module@vger.kernel.org Signed-off-by: Al Viro --- security/selinux/selinuxfs.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 145ee62f205a..0b3155d827a1 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1893,7 +1894,7 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name, #define NULL_FILE_NAME "null" -static int sel_fill_super(struct super_block *sb, void *data, int silent) +static int sel_fill_super(struct super_block *sb, struct fs_context *fc) { struct selinux_fs_info *fsi; int ret; @@ -2009,10 +2010,19 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) return ret; } -static struct dentry *sel_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sel_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, sel_fill_super); + return get_tree_single(fc, sel_fill_super); +} + +static const struct fs_context_operations sel_context_ops = { + .get_tree = sel_get_tree, +}; + +static int sel_init_fs_context(struct fs_context *fc) +{ + fc->ops = &sel_context_ops; + return 0; } static void sel_kill_sb(struct super_block *sb) @@ -2023,7 +2033,7 @@ static void sel_kill_sb(struct super_block *sb) static struct file_system_type sel_fs_type = { .name = "selinuxfs", - .mount = sel_mount, + .init_fs_context = sel_init_fs_context, .kill_sb = sel_kill_sb, }; From 5afdd0f1e6a7e56264fd933065884a7903375106 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 25 Mar 2019 16:38:31 +0000 Subject: [PATCH 59/63] vfs: Convert smackfs to use the new mount API Convert the smackfs 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: Casey Schaufler cc: linux-security-module@vger.kernel.org Signed-off-by: Al Viro --- security/smack/smackfs.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 47f73a0dabb1..f2fb563af431 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "smack.h" #define BEBITS (sizeof(__be32) * 8) @@ -2820,14 +2821,13 @@ static const struct file_operations smk_ptrace_ops = { /** * smk_fill_super - fill the smackfs superblock * @sb: the empty superblock - * @data: unused - * @silent: unused + * @fc: unused * * Fill in the well known entries for the smack filesystem * * Returns 0 on success, an error code on failure */ -static int smk_fill_super(struct super_block *sb, void *data, int silent) +static int smk_fill_super(struct super_block *sb, struct fs_context *fc) { int rc; @@ -2897,25 +2897,35 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) } /** - * smk_mount - get the smackfs superblock - * @fs_type: passed along without comment - * @flags: passed along without comment - * @dev_name: passed along without comment - * @data: passed along without comment + * smk_get_tree - get the smackfs superblock + * @fc: The mount context, including any options * * Just passes everything along. * * Returns what the lower level code does. */ -static struct dentry *smk_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int smk_get_tree(struct fs_context *fc) { - return mount_single(fs_type, flags, data, smk_fill_super); + return get_tree_single(fc, smk_fill_super); +} + +static const struct fs_context_operations smk_context_ops = { + .get_tree = smk_get_tree, +}; + +/** + * smk_init_fs_context - Initialise a filesystem context for smackfs + * @fc: The blank mount context + */ +static int smk_init_fs_context(struct fs_context *fc) +{ + fc->ops = &smk_context_ops; + return 0; } static struct file_system_type smk_fs_type = { .name = "smackfs", - .mount = smk_mount, + .init_fs_context = smk_init_fs_context, .kill_sb = kill_litter_super, }; From 14a253ce4210cd2ef133b392062477e9d656db4a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 May 2019 15:59:57 -0400 Subject: [PATCH 60/63] 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(-) 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) From fd3e007f6c6a0f677e4ee8aca4b9bab8ad6cab9a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 May 2019 17:48:35 -0400 Subject: [PATCH 61/63] 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(-) 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; } From 33488845f211afcdb7e5c00a3152890e06cdc78e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 31 May 2019 20:09:15 -0400 Subject: [PATCH 62/63] 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(-) 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); From 037f11b4752f717201143a1dc5d6acf3cb71ddfa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Jun 2019 18:09:44 -0400 Subject: [PATCH 63/63] 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(-) 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);