forked from Minki/linux
Merge branch 'work.mount0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
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() ...
This commit is contained in:
commit
933a90bf4f
@ -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,16 +601,18 @@ 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,
|
||||
.init_fs_context = pfmfs_init_fs_context,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
MODULE_ALIAS_FS("pfmfs");
|
||||
|
@ -2104,7 +2104,6 @@ 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);
|
||||
fc->user_ns = get_user_ns(&init_user_ns);
|
||||
fc->global = true;
|
||||
|
@ -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
|
||||
|
@ -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,15 +470,18 @@ 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,
|
||||
.init_fs_context = dax_init_fs_context,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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>
|
||||
|
||||
@ -33,21 +34,15 @@
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -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 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 = {
|
||||
@ -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;
|
||||
|
||||
|
@ -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,21 +1729,14 @@ 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,
|
||||
.init_fs_context = vmballoon_init_fs_context,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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>
|
||||
|
||||
@ -31,31 +32,15 @@
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
16
fs/aio.c
16
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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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.
|
||||
|
@ -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 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);
|
||||
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 = {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
80
fs/libfs.c
80
fs/libfs.c
@ -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;
|
||||
}
|
||||
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);
|
||||
static int pseudo_fs_get_tree(struct fs_context *fc)
|
||||
{
|
||||
return get_tree_nodev(fc, pseudo_fs_fill_super);
|
||||
}
|
||||
EXPORT_SYMBOL(mount_pseudo_xattr);
|
||||
|
||||
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;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
EXPORT_SYMBOL(init_pseudo);
|
||||
|
||||
int simple_open(struct inode *inode, struct file *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();
|
||||
}
|
||||
|
@ -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 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)
|
||||
@ -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");
|
||||
|
16
fs/nsfs.c
16
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,
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
15
fs/pipe.c
15
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,
|
||||
};
|
||||
|
||||
|
@ -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,7 +165,6 @@ 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);
|
||||
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;
|
||||
|
@ -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);
|
||||
|
138
fs/super.c
138
fs/super.c
@ -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
|
||||
* sget - 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
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
@ -72,7 +72,6 @@ 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);
|
||||
fc->user_ns = get_user_ns(netns->user_ns);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
16
include/linux/pseudo_fs.h
Normal file
16
include/linux/pseudo_fs.h
Normal file
@ -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
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,7 +372,6 @@ 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);
|
||||
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);
|
||||
|
@ -2201,7 +2201,6 @@ 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);
|
||||
fc->user_ns = get_user_ns(ctx->ns->user_ns);
|
||||
fc->global = true;
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
14
mm/z3fold.c
14
mm/z3fold.c
@ -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>
|
||||
@ -36,12 +35,14 @@
|
||||
#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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
16
net/socket.c
16
net/socket.c
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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)
|
||||
@ -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");
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user