diff mbox series

[2/5] kernfs: Provide a fill_super hook for the subclass filesystem

Message ID 154655904912.3032.14601659851271963173.stgit@warthog.procyon.org.uk (mailing list archive)
State New, archived
Headers show
Series [1/5] cgroup2: Always apply root flags on successful superblock obtainance | expand

Commit Message

David Howells Jan. 3, 2019, 11:44 p.m. UTC
Provide a fill_super hook for a subclass filesystem to use to get a
reference on the resource it attaches to struct kernfs_super_info::root.

Without this, error handling becomes tricky in the event that, say,
kernfs_get_inode() fails in kernfs_fill_super() as the superblock
destructor will be invoked before kernfs_get_tree() returns.

Fixes: b3678086951a ("kernfs, sysfs, cgroup, intel_rdt: Support fs_context")
Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/kernfs/mount.c      |   13 +++++++++++--
 include/linux/kernfs.h |    1 +
 2 files changed, 12 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 3b61a4bb02c4..f04173d29845 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -217,11 +217,13 @@  struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
 	} while (true);
 }
 
-static int kernfs_fill_super(struct super_block *sb, struct kernfs_fs_context *kfc)
+static int kernfs_fill_super(struct super_block *sb, struct fs_context *fc)
 {
+	struct kernfs_fs_context *kfc = fc->fs_private;
 	struct kernfs_super_info *info = kernfs_info(sb);
 	struct inode *inode;
 	struct dentry *root;
+	int ret;
 
 	info->sb = sb;
 	/* Userspace would break if executables or devices appear on sysfs */
@@ -238,6 +240,12 @@  static int kernfs_fill_super(struct super_block *sb, struct kernfs_fs_context *k
 	/* sysfs dentries and inodes don't require IO to create */
 	sb->s_shrink.seeks = 0;
 
+	if (kfc->fill_super) {
+		ret = kfc->fill_super(sb, fc);
+		if (ret < 0)
+			return ret;
+	}
+
 	/* get root inode, initialize and unlock it */
 	mutex_lock(&kernfs_mutex);
 	inode = kernfs_get_inode(sb, info->root->kn);
@@ -290,6 +298,7 @@  const void *kernfs_super_ns(struct super_block *sb)
 /**
  * kernfs_get_tree - kernfs filesystem access/retrieval helper
  * @fc: The filesystem context.
+ * @fill_super: The subclass's superblock initialiser function
  *
  * This is to be called from each kernfs user's fs_context->ops->get_tree()
  * implementation, which should set the specified ->@fs_type and ->@flags, and
@@ -321,7 +330,7 @@  int kernfs_get_tree(struct fs_context *fc)
 
 		kfc->new_sb_created = true;
 
-		error = kernfs_fill_super(sb, kfc);
+		error = kernfs_fill_super(sb, fc);
 		if (error) {
 			deactivate_locked_super(sb);
 			return error;
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 60ae0f862a79..a68e3fdd428c 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -277,6 +277,7 @@  struct kernfs_fs_context {
 	struct kernfs_root	*root;		/* Root of the hierarchy being mounted */
 	void			*ns_tag;	/* Namespace tag of the mount (or NULL) */
 	unsigned long		magic;		/* File system specific magic number */
+	int (*fill_super)(struct super_block *sb, struct fs_context *fc);
 
 	/* The following are set/used by kernfs_mount() */
 	bool			new_sb_created;	/* Set to T if we allocated a new sb */