[<prev] [next>] [day] [month] [year] [list]
Message-ID: <155257975796.13720.9965979295958004676.stgit@warthog.procyon.org.uk>
Date: Thu, 14 Mar 2019 16:09:17 +0000
From: David Howells <dhowells@...hat.com>
To: viro@...iv.linux.org.uk
Cc: linux-fsdevel@...r.kernel.org, dhowells@...hat.com,
linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH 02/38] vfs: Provide a mount_pseudo-replacement for fs_context
Signed-off-by: David Howells <dhowells@...hat.com>
cc: linux-fsdevel@...r.kernel.org
---
fs/libfs.c | 93 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs_context.h | 7 +++
2 files changed, 100 insertions(+)
diff --git a/fs/libfs.c b/fs/libfs.c
index 0fb590d79f30..ceaf69c885c2 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -16,6 +16,7 @@
#include <linux/exportfs.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* sync_mapping_buffers */
+#include <linux/fs_context.h>
#include <linux/uaccess.h>
@@ -233,6 +234,98 @@ static const struct super_operations simple_super_operations = {
.statfs = simple_statfs,
};
+struct pseudo_fs_context {
+ struct qstr d_name;
+ const struct super_operations *ops;
+ const struct xattr_handler **xattr;
+ const struct dentry_operations *dops;
+ unsigned long magic;
+};
+
+static int pseudo_fs_get_tree(struct fs_context *fc)
+{
+ struct pseudo_fs_context *ctx = fc->fs_private;
+ struct super_block *s;
+ struct dentry *dentry;
+ struct inode *root;
+
+ s = sget_userns(fc->fs_type, NULL, set_anon_super, SB_KERNMOUNT|SB_NOUSER,
+ &init_user_ns, NULL);
+ if (IS_ERR(s))
+ return PTR_ERR(s);
+
+ s->s_maxbytes = MAX_LFS_FILESIZE;
+ s->s_blocksize = PAGE_SIZE;
+ s->s_blocksize_bits = PAGE_SHIFT;
+ s->s_magic = ctx->magic;
+ s->s_op = ctx->ops ?: &simple_super_operations;
+ s->s_xattr = ctx->xattr;
+ s->s_time_gran = 1;
+ root = new_inode(s);
+ if (!root)
+ goto Enomem;
+ /*
+ * since this is the first inode, make it number 1. New inodes created
+ * after this must take care not to collide with it (by passing
+ * max_reserved of 1 to iunique).
+ */
+ root->i_ino = 1;
+ root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
+ root->i_atime = root->i_mtime = root->i_ctime = current_time(root);
+ dentry = __d_alloc(s, &ctx->d_name);
+ if (!dentry) {
+ iput(root);
+ goto Enomem;
+ }
+ d_instantiate(dentry, root);
+ s->s_root = dentry;
+ s->s_d_op = ctx->dops;
+ s->s_flags |= SB_ACTIVE;
+ fc->root = dget(s->s_root);
+ return 0;
+
+Enomem:
+ deactivate_locked_super(s);
+ return -ENOMEM;
+}
+
+static void pseudo_fs_free(struct fs_context *fc)
+{
+ 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)
+ */
+int vfs_init_pseudo_fs_context(struct fs_context *fc,
+ const char *name,
+ const struct super_operations *ops,
+ const struct xattr_handler **xattr,
+ const struct dentry_operations *dops,
+ unsigned long magic)
+{
+ struct pseudo_fs_context *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->d_name = (struct qstr)QSTR_INIT(name, strlen(name));
+ ctx->ops = ops;
+ ctx->xattr = xattr;
+ ctx->dops = dops;
+ ctx->magic = magic;
+ fc->fs_private = ctx;
+ fc->ops = &pseudo_fs_context_ops;
+ return 0;
+}
+EXPORT_SYMBOL(vfs_init_pseudo_fs_context);
+
/*
* Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
* will never be mountable)
diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
index 98b44ad89378..a779022d06f5 100644
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -121,6 +121,13 @@ extern int generic_parse_monolithic(struct fs_context *fc, void *data);
extern int vfs_get_tree(struct fs_context *fc);
extern void put_fs_context(struct fs_context *fc);
+extern int vfs_init_pseudo_fs_context(struct fs_context *fc,
+ const char *name,
+ const struct super_operations *ops,
+ const struct xattr_handler **xattr,
+ const struct dentry_operations *dops,
+ unsigned long magic);
+
/*
* sget() wrapper to be called from the ->get_tree() op.
*/
Powered by blists - more mailing lists