Merge branch 'work.mount0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 19 Jul 2019 17:42:02 +0000 (10:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 19 Jul 2019 17:42:02 +0000 (10:42 -0700)
Pull vfs mount updates from Al Viro:
 "The first part of mount updates.

  Convert filesystems to use the new mount API"

* 'work.mount0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (63 commits)
  mnt_init(): call shmem_init() unconditionally
  constify ksys_mount() string arguments
  don't bother with registering rootfs
  init_rootfs(): don't bother with init_ramfs_fs()
  vfs: Convert smackfs to use the new mount API
  vfs: Convert selinuxfs to use the new mount API
  vfs: Convert securityfs to use the new mount API
  vfs: Convert apparmorfs to use the new mount API
  vfs: Convert openpromfs to use the new mount API
  vfs: Convert xenfs to use the new mount API
  vfs: Convert gadgetfs to use the new mount API
  vfs: Convert oprofilefs to use the new mount API
  vfs: Convert ibmasmfs to use the new mount API
  vfs: Convert qib_fs/ipathfs to use the new mount API
  vfs: Convert efivarfs to use the new mount API
  vfs: Convert configfs to use the new mount API
  vfs: Convert binfmt_misc to use the new mount API
  convenience helper: get_tree_single()
  convenience helper get_tree_nodev()
  vfs: Kill sget_userns()
  ...

60 files changed:
arch/ia64/kernel/perfmon.c
arch/x86/kernel/cpu/resctrl/rdtgroup.c
drivers/base/devtmpfs.c
drivers/dax/super.c
drivers/dma-buf/dma-buf.c
drivers/gpu/drm/drm_drv.c
drivers/infiniband/hw/qib/qib_fs.c
drivers/misc/cxl/api.c
drivers/misc/ibmasm/ibmasmfs.c
drivers/misc/vmw_balloon.c
drivers/oprofile/oprofilefs.c
drivers/scsi/cxlflash/ocxl_hw.c
drivers/usb/gadget/legacy/inode.c
drivers/virtio/virtio_balloon.c
drivers/xen/xenfs/super.c
fs/aio.c
fs/anon_inodes.c
fs/binfmt_misc.c
fs/block_dev.c
fs/btrfs/tests/btrfs-tests.c
fs/configfs/mount.c
fs/d_path.c
fs/efivarfs/super.c
fs/fs_parser.c
fs/fsopen.c
fs/fuse/control.c
fs/hugetlbfs/inode.c
fs/internal.h
fs/libfs.c
fs/namespace.c
fs/nfsd/nfsctl.c
fs/nsfs.c
fs/openpromfs/inode.c
fs/pipe.c
fs/proc/root.c
fs/ramfs/inode.c
fs/super.c
fs/sysfs/mount.c
include/linux/dcache.h
include/linux/fs.h
include/linux/fs_context.h
include/linux/init.h
include/linux/pseudo_fs.h [new file with mode: 0644]
include/linux/ramfs.h
include/linux/syscalls.h
include/uapi/linux/magic.h
init/do_mounts.c
init/main.c
ipc/mqueue.c
kernel/cgroup/cgroup.c
kernel/cgroup/cpuset.c
mm/shmem.c
mm/z3fold.c
mm/zsmalloc.c
net/socket.c
net/sunrpc/rpc_pipe.c
security/apparmor/apparmorfs.c
security/inode.c
security/selinux/selinuxfs.c
security/smack/smackfs.c

index 7c52bd2695a21b57665c5db8b7d5c0eb0cd4c325..a23c3938a1c47159c475f9db52295e04edb7a420 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/smp.h>
 #include <linux/pagemap.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/rcupdate.h>
@@ -600,17 +601,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, "pfm:", 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");
 
index bf3034994754d34ae097b62bf78c5199a1019f3e..a46dee8e78db4a22dafd063a7cf38187f44dc457 100644 (file)
@@ -2104,8 +2104,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;
index 0dbc43068eeb3cd4658daa6a4b65b8bf6a9ea0cd..ba5c80903efec8ee4d94fec5dc6ed868cd0ee617 100644 (file)
@@ -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
index 8ab12068eea33ff738f220f10aad993f7f9adc69..26a654dbc69a26d2b0dfb46ac0ba57cc0fb6c9a9 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/pagemap.h>
 #include <linux/module.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/magic.h>
 #include <linux/genhd.h>
 #include <linux/pfn_t.h>
@@ -469,16 +470,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:", &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)
@@ -665,10 +669,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);
@@ -679,8 +679,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;
@@ -689,7 +687,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);
 }
 
index dc4b2c521d79a0d3fb2869d7a7da0c378f0dd1f6..f45bfb29ef960346ae122dc94c067286fcf8c7de 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/reservation.h>
 #include <linux/mm.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 
 #include <uapi/linux/dma-buf.h>
 #include <uapi/linux/magic.h>
@@ -59,16 +60,20 @@ static const struct dentry_operations dma_buf_dentry_ops = {
 
 static struct vfsmount *dma_buf_mnt;
 
-static struct dentry *dma_buf_fs_mount(struct file_system_type *fs_type,
-               int flags, const char *name, void *data)
+static int dma_buf_fs_init_context(struct fs_context *fc)
 {
-       return mount_pseudo(fs_type, "dmabuf:", NULL, &dma_buf_dentry_ops,
-                       DMA_BUF_MAGIC);
+       struct pseudo_fs_context *ctx;
+
+       ctx = init_pseudo(fc, DMA_BUF_MAGIC);
+       if (!ctx)
+               return -ENOMEM;
+       ctx->dops = &dma_buf_dentry_ops;
+       return 0;
 }
 
 static struct file_system_type dma_buf_fs_type = {
        .name = "dmabuf",
-       .mount = dma_buf_fs_mount,
+       .init_fs_context = dma_buf_fs_init_context,
        .kill_sb = kill_anon_super,
 };
 
index fe0ce86c280f10a1875c926ebbde94d2a267d3c4..9d00947ca447fc9555d2abc4194bf95dad799207 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/slab.h>
 #include <linux/srcu.h>
 
@@ -535,28 +536,15 @@ 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)
+static int drm_fs_init_fs_context(struct fs_context *fc)
 {
-       return mount_pseudo(fs_type,
-                           "drm:",
-                           &drm_fs_sops,
-                           &drm_fs_dops,
-                           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,
 };
 
index ceb42d94841226b15b5ef9d78f86f2b68c82084d..41a569558a1579908e8fdf0f5164d8c703ddd7b3 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
@@ -506,7 +507,7 @@ bail:
  * 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 @@ bail:
        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");
index a450694d5a62fad7baa021164633e498bc2391dc..b493de962153ba627af0e3b7dd3f059d5620e91e 100644 (file)
@@ -9,6 +9,7 @@
 #include <misc/cxl.h>
 #include <linux/module.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/sched/mm.h>
 #include <linux/mmu_context.h>
 
 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)
+static int cxl_fs_init_fs_context(struct fs_context *fc)
 {
-       return mount_pseudo(fs_type, "cxl:", NULL, &cxl_fs_dops,
-                       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,
 };
 
index 4989dcb2df149cc9e33e09366093bd79e5eca201..35fec1bf1b3dd736dea8d46a662453e24078ae43 100644 (file)
@@ -60,6 +60,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
@@ -74,13 +75,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 int ibmasmfs_get_tree(struct fs_context *fc)
+{
+       return get_tree_single(fc, ibmasmfs_fill_super);
+}
 
-static struct dentry *ibmasmfs_mount(struct file_system_type *fst,
-                       int flags, const char *name, void *data)
+static const struct fs_context_operations ibmasmfs_context_ops = {
+       .get_tree       = ibmasmfs_get_tree,
+};
+
+static int ibmasmfs_init_fs_context(struct fs_context *fc)
 {
-       return mount_single(fst, flags, data, ibmasmfs_fill_super);
+       fc->ops = &ibmasmfs_context_ops;
+       return 0;
 }
 
 static const struct super_operations ibmasmfs_s_ops = {
@@ -93,12 +102,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;
 
index 97b58e7ad901adfab306cdf62b15364cda21880b..8840299420e0b287f3cd81733a1c13a0c7957fb0 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/balloon_compaction.h>
 #include <linux/vmw_vmci_defs.h>
 #include <linux/vmw_vmci_api.h>
@@ -1728,22 +1729,15 @@ static inline void vmballoon_debugfs_exit(struct vmballoon *b)
 
 #ifdef CONFIG_BALLOON_COMPACTION
 
-static struct dentry *vmballoon_mount(struct file_system_type *fs_type,
-                                     int flags, const char *dev_name,
-                                     void *data)
+static int vmballoon_init_fs_context(struct fs_context *fc)
 {
-       static const struct dentry_operations ops = {
-               .d_dname = simple_dname,
-       };
-
-       return mount_pseudo(fs_type, "balloon-vmware:", NULL, &ops,
-                           BALLOON_VMW_MAGIC);
+       return init_pseudo(fc, BALLOON_VMW_MAGIC) ? 0 : -ENOMEM;
 }
 
 static struct file_system_type vmballoon_fs = {
-       .name           = "balloon-vmware",
-       .mount          = vmballoon_mount,
-       .kill_sb        = kill_anon_super,
+       .name                   = "balloon-vmware",
+       .init_fs_context        = vmballoon_init_fs_context,
+       .kill_sb                = kill_anon_super,
 };
 
 static struct vfsmount *vmballoon_mnt;
index 4ea08979312ca3e86804d5c7fa3e49be5969606a..0875f2f122b3182104155e5eca1956d5efd2d259 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/oprofile.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/pagemap.h>
 #include <linux/uaccess.h>
 
@@ -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");
index 96740c6fcd92dae0e0999b54f51acc6bdebea3db..7018cd8025694b6c7a7cac540ac959ea69e5a983 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/idr.h>
 #include <linux/module.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/poll.h>
 #include <linux/sched/signal.h>
 
 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.
- * @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, "ocxlflash:", NULL, &ocxlflash_fs_dops,
-                           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,
 };
 
index 249277d0e53f98952422a3fe59befbc738905fa5..b47938dff1a22e11092413b68fd57ae35d2cc2a7 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/pagemap.h>
 #include <linux/uts.h>
 #include <linux/wait.h>
@@ -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 @@ Enomem:
 }
 
 /* "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");
index 44339fc87cc799e54d8916667cdf35391b455901..226fbb995fb0612ad623ad3db36856162dba16e9 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/mount.h>
 #include <linux/magic.h>
+#include <linux/pseudo_fs.h>
 
 /*
  * Balloon device works in 4K page units.  So each page is pointed to by
@@ -745,20 +746,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)
 {
-       static const struct dentry_operations ops = {
-               .d_dname = simple_dname,
-       };
-
-       return mount_pseudo(fs_type, "balloon-kvm:", NULL, &ops,
-                               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,
 };
 
index 20c1448f1ce71d0d5a163c2dc415a480a06ac990..d7d64235010d415922b174a3a1c1a39cdb96be4f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/magic.h>
 
 #include <xen/xen.h>
@@ -43,7 +44,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 },
@@ -68,17 +69,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");
index 8b3aa2739906589c8e4c5a8627378b883ac5f430..01e0fb9ae45aed3b1e10b3bfe25b878f393e0ab6 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -42,6 +42,7 @@
 #include <linux/ramfs.h>
 #include <linux/percpu-refcount.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 
 #include <asm/kmap_types.h>
 #include <linux/uaccess.h>
@@ -249,15 +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, "aio:", 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
@@ -268,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);
index c2b8663f5b00e5f3f14e949a7e518b072fd6bd44..89714308c25b8fbf9e93fbe60d25aedba6004182 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/magic.h>
 #include <linux/anon_inodes.h>
+#include <linux/pseudo_fs.h>
 
 #include <linux/uaccess.h>
 
@@ -39,16 +40,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, "anon_inode:", 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,
 };
 
index b8e145552ec7e817d31ca9c314385f31b1bd1bdd..cdb45829354d9f6db769ac0d83db44fed57c919e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/pagemap.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/fs_context.h>
 #include <linux/syscalls.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
@@ -821,7 +822,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[] = {
@@ -836,10 +837,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 = {
@@ -850,7 +860,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");
index f00b569a9f895043ca87267bec036962dc72f756..4707dfff991b55ddc9399e4f28797d81feae5e18 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/uio.h>
 #include <linux/namei.h>
 #include <linux/log2.h>
@@ -821,19 +822,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:", &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,
 };
 
index 9238fd4f1734082a37e8e54f324818ab792e18bc..1e3ba4949399536929b2d6a951d04aec69357fb5 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/fs.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/magic.h>
 #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:", &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,
 };
 
index 791304fdde9d60f4e5783bc8d7ee65019e0cd996..55438dd58189934e7498f88a461c4dc6f83d2ece 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/mount.h>
+#include <linux/fs_context.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -52,7 +53,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;
@@ -88,16 +89,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");
index e8fce6b1174fb4a250da8c4f19a2981da9dc85d6..a7d0a96b35ce5ebf47dec83bce25d531e9943af4 100644 (file)
@@ -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.
index 5bc3c4a4c563ddd169d761a276aad0ec4501c172..fa4f6447ddad690f04cc6d4fddef833e39ff45ac 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/ctype.h>
 #include <linux/efi.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/ucs2_string.h>
@@ -28,8 +29,6 @@ static const struct super_operations efivarfs_ops = {
        .evict_inode = efivarfs_evict_inode,
 };
 
-static struct super_block *efivarfs_sb;
-
 /*
  * Compare two efivarfs file names.
  *
@@ -188,14 +187,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;
@@ -223,16 +220,24 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
        return err;
 }
 
-static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
-                                   int flags, const char *dev_name, void *data)
+static int efivarfs_get_tree(struct fs_context *fc)
+{
+       return get_tree_single(fc, efivarfs_fill_super);
+}
+
+static const struct fs_context_operations efivarfs_context_ops = {
+       .get_tree       = efivarfs_get_tree,
+};
+
+static int efivarfs_init_fs_context(struct fs_context *fc)
 {
-       return mount_single(fs_type, flags, data, efivarfs_fill_super);
+       fc->ops = &efivarfs_context_ops;
+       return 0;
 }
 
 static void efivarfs_kill_sb(struct super_block *sb)
 {
        kill_litter_super(sb);
-       efivarfs_sb = NULL;
 
        /* Remove all entries and destroy */
        __efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL, NULL);
@@ -241,7 +246,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,
 };
 
index 0d388faa25d16aa8768f655611b0ece06b1707d3..460ea4206fa25cd8121271cd83407ab0074e7aac 100644 (file)
@@ -264,6 +264,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);
index a8bf83ce8d4e16cefe6da9106c8c9b4d1f71b9dc..043ffa8dc2637d88b813f223f459ac16ed76f150 100644 (file)
@@ -226,6 +226,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)
index 14ce1e47f980e905b7ad806dbdcbeb6522ad8ffe..c23f6f243ad4224c8f9f5c2e1a8466a32ebf99c6 100644 (file)
@@ -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 = {
index 1dcc57189382bc5c16b6e06dd82d32a342ec944f..a478df03565179d1aa07c8db52c04a72421241f5 100644 (file)
@@ -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)
index 2f3c3de51fad6eebbd68c1dc349a5171bf986b56..b9bad2d30cef30d7efcb2d1d984587054de2c694 100644 (file)
@@ -14,6 +14,7 @@ struct path;
 struct mount;
 struct shrink_control;
 struct fs_context;
+struct user_namespace;
 
 /*
  * block_dev.c
@@ -107,6 +108,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 fs_context *);
 
 /*
  * open.c
@@ -154,6 +156,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
index 7e52e77692ec5114f3669e20733952310c3e6533..c9b2850c0f7ce622443a960c2a1dbb9f03177c01 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/exportfs.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h> /* sync_mapping_buffers */
+#include <linux/fs_context.h>
+#include <linux/pseudo_fs.h>
 
 #include <linux/uaccess.h>
 
@@ -236,34 +238,22 @@ static const struct super_operations simple_super_operations = {
        .statfs         = simple_statfs,
 };
 
-/*
- * 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,
-       const struct super_operations *ops, const struct xattr_handler **xattr,
-       const struct dentry_operations *dops, unsigned long magic)
+static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc)
 {
-       struct super_block *s;
-       struct dentry *dentry;
+       struct pseudo_fs_context *ctx = fc->fs_private;
        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);
-       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_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;
+               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
@@ -272,22 +262,48 @@ 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);
-               goto Enomem;
+       s->s_root = d_make_root(root);
+       if (!s->s_root)
+               return -ENOMEM;
+       s->s_d_op = ctx->dops;
+       return 0;
+}
+
+static int pseudo_fs_get_tree(struct fs_context *fc)
+{
+       return get_tree_nodev(fc, pseudo_fs_fill_super);
+}
+
+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;
+               fc->sb_flags |= SB_NOUSER;
+               fc->global = true;
        }
-       d_instantiate(dentry, root);
-       s->s_root = dentry;
-       s->s_d_op = dops;
-       s->s_flags |= SB_ACTIVE;
-       return dget(s->s_root);
-
-Enomem:
-       deactivate_locked_super(s);
-       return ERR_PTR(-ENOMEM);
+       return ctx;
 }
-EXPORT_SYMBOL(mount_pseudo_xattr);
+EXPORT_SYMBOL(init_pseudo);
 
 int simple_open(struct inode *inode, struct file *file)
 {
index 6fbc9126367a1cf6db621faa575fd709e114002b..f0d664adb9ba731abcfff90f886b3f03a923381f 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/sched/task.h>
 #include <uapi/linux/mount.h>
 #include <linux/fs_context.h>
+#include <linux/shmem_fs.h>
 
 #include "pnode.h"
 #include "internal.h"
@@ -2788,6 +2789,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)
@@ -3295,8 +3298,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;
@@ -3687,13 +3690,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");
 
@@ -3746,6 +3744,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();
 }
index 0a9a49ded546355379379c2529ef70c2f217953e..13c548733860cca6414b23bc30caea2d64c69b02 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 #include <linux/namei.h>
 #include <linux/ctype.h>
+#include <linux/fs_context.h>
 
 #include <linux/sunrpc/svcsock.h>
 #include <linux/lockd/lockd.h>
@@ -1337,7 +1338,7 @@ void nfsd_client_rmdir(struct dentry *dentry)
        inode_unlock(dir);
 }
 
-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)
 {
        struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
                                                        nfsd_net_id);
@@ -1372,7 +1373,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 #endif
                /* last one */ {""}
        };
-       get_net(sb->s_fs_info);
+
        ret = simple_fill_super(sb, 0x6e667364, nfsd_files);
        if (ret)
                return ret;
@@ -1381,14 +1382,31 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
                return PTR_ERR(dentry);
        nn->nfsd_client_dir = dentry;
        return 0;
+}
 
+static int nfsd_fs_get_tree(struct fs_context *fc)
+{
+       fc->s_fs_info = get_net(fc->net_ns);
+       return vfs_get_super(fc, vfs_get_keyed_super, nfsd_fill_super);
 }
 
-static struct dentry *nfsd_mount(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data)
+static void nfsd_fs_free_fc(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);
+       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)
@@ -1402,7 +1420,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");
index e3bf08c5af4114b88a26f507c3679a3418ed40c5..a0431642c6b55f4d80f66ddb29d7f0f8f5314bf8 100644 (file)
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/proc_ns.h>
@@ -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:", &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,
 };
 
index e6cb7689fec44651d2f6eb89d2e59e3e7c8a9053..40c8c2e32fa3e5617c818e782eed34ea61670d29 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
@@ -375,7 +376,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;
@@ -409,16 +410,25 @@ out_no_root:
        return ret;
 }
 
-static struct dentry *openprom_mount(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data)
+static int openpromfs_get_tree(struct fs_context *fc)
 {
-       return mount_single(fs_type, flags, data, openprom_fill_super);
+       return get_tree_single(fc, openprom_fill_super);
+}
+
+static const struct fs_context_operations openpromfs_context_ops = {
+       .get_tree       = openpromfs_get_tree,
+};
+
+static int openpromfs_init_fs_context(struct fs_context *fc)
+{
+       fc->ops = &openpromfs_context_ops;
+       return 0;
 }
 
 static struct file_system_type openprom_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "openpromfs",
-       .mount          = openprom_mount,
+       .init_fs_context = openpromfs_init_fs_context,
        .kill_sb        = kill_anon_super,
 };
 MODULE_ALIAS_FS("openpromfs");
index 41065901106b09d4365ebc13ee6cfa7b6465339b..8a2ab2f974bd4945f4038923f99c7393a0412ed9 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -14,6 +14,7 @@
 #include <linux/fs.h>
 #include <linux/log2.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/magic.h>
 #include <linux/pipe_fs_i.h>
 #include <linux/uio.h>
@@ -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, "pipe:", &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,
 };
 
index 522199e9525e5485d0ce3805d1e962b3b254a329..33f72d1b92cca60ef9f187ac7ccfbc873c0bf7e1 100644 (file)
@@ -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;
index 11201b2d06b927814215bbea7451540f4bb44fa3..733c6b4193dc86feec5dd4e2291f11a896dcb0e7 100644 (file)
@@ -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);
index 2739f57515f81d8fad4bc4edc83d4c98773308d9..113c58f194255e3fc57166467018d5eab565548a 100644 (file)
@@ -476,6 +476,17 @@ void generic_shutdown_super(struct super_block *sb)
 
 EXPORT_SYMBOL(generic_shutdown_super);
 
+bool mount_capable(struct fs_context *fc)
+{
+       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(user_ns, CAP_SYS_ADMIN);
+}
+
 /**
  * sget_fc - Find or create a superblock
  * @fc:        Filesystem context.
@@ -503,20 +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) {
-               /* 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);
-               }
-       }
-
 retry:
        spin_lock(&sb_lock);
        if (test) {
@@ -543,6 +540,7 @@ retry:
        }
        fc->s_fs_info = NULL;
        s->s_type = fc->fs_type;
+       s->s_iflags |= fc->s_iflags;
        strlcpy(s->s_id, s->s_type->name, sizeof(s->s_id));
        list_add_tail(&s->s_list, &super_blocks);
        hlist_add_head(&s->s_instances, &s->s_type->fs_supers);
@@ -565,28 +563,31 @@ share_extant_sb:
 EXPORT_SYMBOL(sget_fc);
 
 /**
- *     sget_userns -   find or create a superblock
- *     @type:  filesystem type superblock should belong to
- *     @test:  comparison callback
- *     @set:   setup callback
- *     @flags: mount flags
- *     @user_ns: User namespace for the super_block
- *     @data:  argument to each of them
+ *     sget    -       find or create a superblock
+ *     @type:    filesystem type superblock should belong to
+ *     @test:    comparison callback
+ *     @set:     setup callback
+ *     @flags:   mount flags
+ *     @data:    argument to each of them
  */
-struct super_block *sget_userns(struct file_system_type *type,
+struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
-                       int flags, struct user_namespace *user_ns,
+                       int flags,
                        void *data)
 {
+       struct user_namespace *user_ns = current_user_ns();
        struct super_block *s = NULL;
        struct super_block *old;
        int err;
 
-       if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) &&
-           !(type->fs_flags & FS_USERNS_MOUNT) &&
-           !capable(CAP_SYS_ADMIN))
-               return ERR_PTR(-EPERM);
+       /* 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) {
@@ -627,39 +628,6 @@ retry:
        register_shrinker_prepared(&s->s_shrink);
        return s;
 }
-
-EXPORT_SYMBOL(sget_userns);
-
-/**
- *     sget    -       find or create a superblock
- *     @type:    filesystem type superblock should belong to
- *     @test:    comparison callback
- *     @set:     setup callback
- *     @flags:   mount flags
- *     @data:    argument to each of them
- */
-struct super_block *sget(struct file_system_type *type,
-                       int (*test)(struct super_block *,void *),
-                       int (*set)(struct super_block *,void *),
-                       int flags,
-                       void *data)
-{
-       struct user_namespace *user_ns = current_user_ns();
-
-       /* We don't yet pass the user namespace of the parent
-        * mount through to here so always use &init_user_ns
-        * until that changes.
-        */
-       if (flags & SB_SUBMOUNT)
-               user_ns = &init_user_ns;
-
-       /* 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);
-}
-
 EXPORT_SYMBOL(sget);
 
 void drop_super(struct super_block *sb)
@@ -1147,50 +1115,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;
-
-       /* 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))
-               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);
@@ -1274,6 +1198,22 @@ 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);
+
+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)
 {
index 1b56686ab178dc6d4363ea2f76fde6cff90926da..db81cfbab9d60700f3d743ba97a589ea63637bdd 100644 (file)
@@ -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;
index 5e0eadf7de557fde687135a02a7ae2d8cb4304bb..9451011ac014ab179355720276fceb6bb3987025 100644 (file)
@@ -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);
index 75f2ed289a3f364644918f5b36ea14c4f3cf5ef8..56b8e358af5c1e6c6e02663a6722909e0a13d70d 100644 (file)
@@ -2210,9 +2210,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,
@@ -2252,28 +2249,10 @@ 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 *),
                        int flags, void *data);
-extern struct dentry *mount_pseudo_xattr(struct file_system_type *, char *,
-                                        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,
-            const struct super_operations *ops,
-            const struct dentry_operations *dops, unsigned long magic)
-{
-       return mount_pseudo_xattr(fs_type, name, ops, NULL, dops, magic);
-}
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
 #define fops_get(fops) \
index 4933187d5b9a38c85f80af8923c26b67b4c7aef6..7c6fe3d47fa6aef9ac550938589e64bac83f925b 100644 (file)
@@ -99,6 +99,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 */
@@ -146,6 +147,12 @@ 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 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;
 
index 5255069f5a9fa101819ac397cb09e14a3cde6d21..212fc9e2f691a17c48262248e404159ba1f2b94e 100644 (file)
@@ -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[];
@@ -146,7 +148,8 @@ 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)
 extern bool rodata_enabled;
diff --git a/include/linux/pseudo_fs.h b/include/linux/pseudo_fs.h
new file mode 100644 (file)
index 0000000..eceda1d
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __LINUX_PSEUDO_FS__
+#define __LINUX_PSEUDO_FS__
+
+#include <linux/fs_context.h>
+
+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
index 5ef7d54caac23ecd957145a407cb95f29542d109..ee582bdb7fdaaa8eb35fbb07ec88c3494ab0ee47 100644 (file)
@@ -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);
 
index b01d54a5732e3aee142c69295fd1dfbfc780be71..88145da7d14078ff4af7594271d7411d7c8eba61 100644 (file)
@@ -1231,8 +1231,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);
index 665e18627f78ca9bb4e744f07a6a0e6b74190469..1274c692e59c5474fcb89a4e75fc8198831b7591 100644 (file)
@@ -92,5 +92,6 @@
 #define BALLOON_KVM_MAGIC      0x13661366
 #define ZSMALLOC_MAGIC         0x58295829
 #define DMA_BUF_MAGIC          0x444d4142      /* "DMAB" */
+#define Z3FOLD_MAGIC           0x33
 
 #endif /* __LINUX_MAGIC_H__ */
index 2d1ea3028454313ac6a6a3b02c7b89b82b97ae11..53cb37b66227f6a6d484bc961edd4bf99b811541 100644 (file)
@@ -630,41 +630,23 @@ 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,
 };
 
-int __init init_rootfs(void)
+void __init init_rootfs(void)
 {
-       int err = register_filesystem(&rootfs_fs_type);
-
-       if (err)
-               return err;
-
        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;
-       } else {
-               err = init_ramfs_fs();
-       }
-
-       if (err)
-               unregister_filesystem(&rootfs_fs_type);
-
-       return err;
 }
index ff5803b0841c62eb9bba845011221f45b0d50f2f..96f8d5af52d61a877d661bfd15ca8fc42e7296ae 100644 (file)
@@ -1025,7 +1025,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();
index 65c351564ad080483714ddf2c9c82b4e86f8c873..7a5a8edc3de3f6f30fa416147618d8e4caba5704 100644 (file)
@@ -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);
index 300b0c416341cd03315b1072b8ad5fdaeb3df942..753afbca549fdaeba9c133c192c1927d1d9c6f3c 100644 (file)
@@ -2201,8 +2201,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;
@@ -2243,6 +2242,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)
 {
@@ -5761,6 +5804,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;
 }
index 863e434a602044ced99a6e484530c1a69465de5a..5aa37531ce76fd3a02896dafa6550d0233c19822 100644 (file)
@@ -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;
index c88a30919ae5b220e66a39f027b55dfd80f6cf2b..626d8c74b973f173d3062ee118580b649d35073a 100644 (file)
@@ -3777,10 +3777,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);
index 6c72b18d8b9cbc9534fd008c16aca33ba539598f..1a029a7432ee56635f9dcde8f4c5ad2b1e2984ed 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/atomic.h>
 #include <linux/sched.h>
 #include <linux/cpumask.h>
-#include <linux/dcache.h>
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/compaction.h>
 #include <linux/percpu.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/fs.h>
 #include <linux/preempt.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/zpool.h>
+#include <linux/magic.h>
 
 /*
  * NCHUNKS_ORDER determines the internal allocation granularity, effectively
@@ -245,19 +246,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)
 {
-       static const struct dentry_operations ops = {
-               .d_dname = simple_dname,
-       };
-
-       return mount_pseudo(fs_type, "z3fold:", NULL, &ops, 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,
 };
 
index db09eb3669c5d9ca630d1cea5ea66d85e2dea70d..57fbb7ced69f3a47111db0f665ec05b26e4186db 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/zsmalloc.h>
 #include <linux/zpool.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/migrate.h>
 #include <linux/pagemap.h>
 #include <linux/fs.h>
@@ -1798,19 +1799,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)
 {
-       static const struct dentry_operations ops = {
-               .d_dname = simple_dname,
-       };
-
-       return mount_pseudo(fs_type, "zsmalloc:", NULL, &ops, 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,
 };
 
index 293d56836f01cd3052ec6b00dc39ce03f085ec73..6a9ab7a8b1d2c5059752a9147c2f0fd1aea4f44d 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/mount.h>
+#include <linux/pseudo_fs.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/compat.h>
@@ -338,19 +339,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, "socket:", &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,
 };
 
index 73bd62979fe763d5419369844868b066822fbb92..748bac601e47df6bcfc3fed63909eeb44db98d23 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 #include <linux/mount.h>
+#include <linux/fs_context.h>
 #include <linux/namei.h>
 #include <linux/fsnotify.h>
 #include <linux/kernel.h>
@@ -1352,11 +1353,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;
 
@@ -1413,12 +1414,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)
+{
+       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)
 {
-       struct net *net = current->nsproxy->net_ns;
-       return mount_ns(fs_type, flags, data, net, net->user_ns, rpc_fill_super);
+       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)
@@ -1446,7 +1464,7 @@ out:
 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");
index 66d0b4245ef6fd11ed1c59fea64e570de6de4015..45d13b6462aa75161bf0b768bf966b1920ca6312 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/capability.h>
 #include <linux/rcupdate.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/poll.h>
 #include <uapi/linux/major.h>
 #include <uapi/linux/magic.h>
@@ -132,7 +133,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;
@@ -145,16 +146,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,
 };
 
index fcff7f08bb1c0a084eca2735ec504bb406e474b1..6c326939750d1a950f2482f352d738f56d5b341d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/sysfs.h>
 #include <linux/kobject.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
@@ -36,7 +37,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;
@@ -50,17 +51,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,
 };
 
index 6f195c7915de0c14ae39fabea3a406f1800e3a32..e6c7643c3fc08219e07b3fd8894abb3a8df4ff1d 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <linux/fs_context.h>
 #include <linux/mount.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
@@ -1891,7 +1892,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;
@@ -2007,10 +2008,19 @@ err:
        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)
@@ -2021,7 +2031,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,
 };
 
index ef0d8712d318fe626d1eace6d2467d96acfb1df4..e3e05c04dbd165b2a7ba42ed9aa73b6e4a9cb593 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/ctype.h>
 #include <linux/audit.h>
 #include <linux/magic.h>
+#include <linux/fs_context.h>
 #include "smack.h"
 
 #define BEBITS (sizeof(__be32) * 8)
@@ -2816,14 +2817,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;
 
@@ -2893,25 +2893,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,
 };