Merge branch 'work.mount0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-block.git] / fs / libfs.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)
 {