Add support for fsinfo() to kernfs and cgroup. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> --- 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 --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,