diff mbox series

[12/25] kernfs, cgroup: Add fsinfo support [ver #13]

Message ID 155905636240.1662.16803705540477209176.stgit@warthog.procyon.org.uk (mailing list archive)
State New, archived
Headers show
Series VFS: Introduce filesystem information query syscall [ver #13] | expand

Commit Message

David Howells May 28, 2019, 3:12 p.m. UTC
Add support for fsinfo() to kernfs and cgroup.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/kernfs/mount.c         |   20 ++++++++++++++++++++
 include/linux/kernfs.h    |    4 ++++
 kernel/cgroup/cgroup-v1.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/cgroup/cgroup.c    |   19 +++++++++++++++++++
 4 files changed, 87 insertions(+)
diff mbox series

Patch

diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 9a4646eecb71..f40d467d274b 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -17,6 +17,7 @@ 
 #include <linux/namei.h>
 #include <linux/seq_file.h>
 #include <linux/exportfs.h>
+#include <linux/fsinfo.h>
 
 #include "kernfs-internal.h"
 
@@ -45,6 +46,22 @@  static int kernfs_sop_show_path(struct seq_file *sf, struct dentry *dentry)
 	return 0;
 }
 
+#ifdef CONFIG_FSINFO
+static int kernfs_sop_fsinfo(struct path *path, struct fsinfo_kparams *params)
+{
+	struct kernfs_root *root = kernfs_root(kernfs_dentry_node(path->dentry));
+	struct kernfs_syscall_ops *scops = root->syscall_ops;
+	int ret;
+
+	if (scops && scops->fsinfo) {
+		ret = scops->fsinfo(root, params);
+		if (ret != -EAGAIN)
+			return ret;
+	}
+	return generic_fsinfo(path, params);
+}
+#endif
+
 const struct super_operations kernfs_sops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
@@ -52,6 +69,9 @@  const struct super_operations kernfs_sops = {
 
 	.show_options	= kernfs_sop_show_options,
 	.show_path	= kernfs_sop_show_path,
+#ifdef CONFIG_FSINFO
+	.fsinfo		= kernfs_sop_fsinfo,
+#endif
 };
 
 /*
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 2bf477f86eb1..d01ec4dc2db1 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -27,6 +27,7 @@  struct super_block;
 struct file_system_type;
 struct poll_table_struct;
 struct fs_context;
+struct fsinfo_kparams;
 
 struct kernfs_fs_context;
 struct kernfs_open_node;
@@ -171,6 +172,9 @@  struct kernfs_node {
  */
 struct kernfs_syscall_ops {
 	int (*show_options)(struct seq_file *sf, struct kernfs_root *root);
+#ifdef CONFIG_FSINFO
+	int (*fsinfo)(struct kernfs_root *root, struct fsinfo_kparams *params);
+#endif
 
 	int (*mkdir)(struct kernfs_node *parent, const char *name,
 		     umode_t mode);
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index 68ca5de7ec27..c8a85dfcac87 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -14,6 +14,7 @@ 
 #include <linux/pid_namespace.h>
 #include <linux/cgroupstats.h>
 #include <linux/fs_parser.h>
+#include <linux/fsinfo.h>
 
 #include <trace/events/cgroup.h>
 
@@ -921,6 +922,46 @@  const struct fs_parameter_description cgroup1_fs_parameters = {
 	.specs		= cgroup1_param_specs,
 };
 
+#ifdef CONFIG_FSINFO
+static int cgroup1_fsinfo(struct kernfs_root *kf_root, struct fsinfo_kparams *params)
+{
+	struct cgroup_root *root = cgroup_root_from_kf(kf_root);
+	struct cgroup_subsys *ss;
+	int ssid;
+
+	switch (params->request) {
+	case FSINFO_ATTR_PARAMETERS:
+		if (root->name[0])
+			fsinfo_note_param(params, "name", root->name);
+
+		if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->cgrp.flags))
+			fsinfo_note_param(params, "clone_children", NULL);
+		if (root->flags & CGRP_ROOT_CPUSET_V2_MODE)
+			fsinfo_note_param(params, "noprefix", NULL);
+		if (root->flags & CGRP_ROOT_NOPREFIX)
+			fsinfo_note_param(params, "noprefix", NULL);
+		if (root->flags & CGRP_ROOT_XATTR)
+			fsinfo_note_param(params, "xattr", NULL);
+
+		spin_lock(&release_agent_path_lock);
+		if (root->release_agent_path[0])
+			fsinfo_note_param(params, "release_agent",
+					  root->release_agent_path);
+		spin_unlock(&release_agent_path_lock);
+
+
+		for_each_subsys(ss, ssid) {
+			if (root->subsys_mask & (1 << ssid))
+				fsinfo_note_param(params, ss->legacy_name, NULL);
+		}
+		return params->usage;
+
+	default:
+		return -EAGAIN; /* Tell kernfs to call generic_fsinfo() */
+	}
+}
+#endif /* CONFIG_FSINFO */
+
 int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
@@ -1114,6 +1155,9 @@  int cgroup1_reconfigure(struct fs_context *fc)
 struct kernfs_syscall_ops cgroup1_kf_syscall_ops = {
 	.rename			= cgroup1_rename,
 	.show_options		= cgroup1_show_options,
+#ifdef CONFIG_FSINFO
+	.fsinfo			= cgroup1_fsinfo,
+#endif
 	.mkdir			= cgroup_mkdir,
 	.rmdir			= cgroup_rmdir,
 	.show_path		= cgroup_show_path,
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 4a0eb465d17e..7e32570905e9 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -55,6 +55,7 @@ 
 #include <linux/nsproxy.h>
 #include <linux/file.h>
 #include <linux/fs_parser.h>
+#include <linux/fsinfo.h>
 #include <linux/sched/cputime.h>
 #include <linux/psi.h>
 #include <net/sock.h>
@@ -1858,6 +1859,21 @@  static int cgroup_show_options(struct seq_file *seq, struct kernfs_root *kf_root
 	return 0;
 }
 
+#ifdef CONFIG_FSINFO
+static int cgroup_fsinfo(struct kernfs_root *kf_root, struct fsinfo_kparams *params)
+{
+	switch (params->request) {
+	case FSINFO_ATTR_PARAMETERS:
+		if (cgrp_dfl_root.flags & CGRP_ROOT_NS_DELEGATE)
+			fsinfo_note_param(params, "nsdelegate", NULL);
+		return params->usage;
+
+	default:
+		return -EAGAIN; /* Tell kernfs to call generic_fsinfo() */
+	}
+}
+#endif /* CONFIG_FSINFO */
+
 static int cgroup_reconfigure(struct fs_context *fc)
 {
 	struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
@@ -5550,6 +5566,9 @@  int cgroup_rmdir(struct kernfs_node *kn)
 
 static struct kernfs_syscall_ops cgroup_kf_syscall_ops = {
 	.show_options		= cgroup_show_options,
+#ifdef CONFIG_FSINFO
+	.fsinfo			= cgroup_fsinfo,
+#endif
 	.mkdir			= cgroup_mkdir,
 	.rmdir			= cgroup_rmdir,
 	.show_path		= cgroup_show_path,