Skip to content

Commit 23bf1b6

Browse files
dhowellsAl Viro
authored andcommitted
kernfs, sysfs, cgroup, intel_rdt: Support fs_context
Make kernfs support superblock creation/mount/remount with fs_context. This requires that sysfs, cgroup and intel_rdt, which are built on kernfs, be made to support fs_context also. Notes: (1) A kernfs_fs_context struct is created to wrap fs_context and the kernfs mount parameters are moved in here (or are in fs_context). (2) kernfs_mount{,_ns}() are made into kernfs_get_tree(). The extra namespace tag parameter is passed in the context if desired (3) kernfs_free_fs_context() is provided as a destructor for the kernfs_fs_context struct, but for the moment it does nothing except get called in the right places. (4) sysfs doesn't wrap kernfs_fs_context since it has no parameters to pass, but possibly this should be done anyway in case someone wants to add a parameter in future. (5) A cgroup_fs_context struct is created to wrap kernfs_fs_context and the cgroup v1 and v2 mount parameters are all moved there. (6) cgroup1 parameter parsing error messages are now handled by invalf(), which allows userspace to collect them directly. (7) cgroup1 parameter cleanup is now done in the context destructor rather than in the mount/get_tree and remount functions. Weirdies: (*) cgroup_do_get_tree() calls cset_cgroup_from_root() with locks held, but then uses the resulting pointer after dropping the locks. I'm told this is okay and needs commenting. (*) The cgroup refcount web. This really needs documenting. (*) cgroup2 only has one root? Add a suggestion from Thomas Gleixner in which the RDT enablement code is placed into its own function. [folded a leak fix from Andrey Vagin] Signed-off-by: David Howells <dhowells@redhat.com> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> cc: Tejun Heo <tj@kernel.org> cc: Li Zefan <lizefan@huawei.com> cc: Johannes Weiner <hannes@cmpxchg.org> cc: cgroups@vger.kernel.org cc: fenghua.yu@intel.com Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent cca8f32 commit 23bf1b6

File tree

8 files changed

+262
-176
lines changed

8 files changed

+262
-176
lines changed

arch/x86/kernel/cpu/resctrl/internal.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <linux/sched.h>
66
#include <linux/kernfs.h>
7+
#include <linux/fs_context.h>
78
#include <linux/jump_label.h>
89

910
#define MSR_IA32_L3_QOS_CFG 0xc81
@@ -40,6 +41,21 @@
4041
#define RMID_VAL_ERROR BIT_ULL(63)
4142
#define RMID_VAL_UNAVAIL BIT_ULL(62)
4243

44+
45+
struct rdt_fs_context {
46+
struct kernfs_fs_context kfc;
47+
bool enable_cdpl2;
48+
bool enable_cdpl3;
49+
bool enable_mba_mbps;
50+
};
51+
52+
static inline struct rdt_fs_context *rdt_fc2context(struct fs_context *fc)
53+
{
54+
struct kernfs_fs_context *kfc = fc->fs_private;
55+
56+
return container_of(kfc, struct rdt_fs_context, kfc);
57+
}
58+
4359
DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
4460

4561
/**

arch/x86/kernel/cpu/resctrl/rdtgroup.c

Lines changed: 116 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/cpu.h>
2525
#include <linux/debugfs.h>
2626
#include <linux/fs.h>
27+
#include <linux/fs_parser.h>
2728
#include <linux/sysfs.h>
2829
#include <linux/kernfs.h>
2930
#include <linux/seq_buf.h>
@@ -32,6 +33,7 @@
3233
#include <linux/sched/task.h>
3334
#include <linux/slab.h>
3435
#include <linux/task_work.h>
36+
#include <linux/user_namespace.h>
3537

3638
#include <uapi/linux/magic.h>
3739

@@ -1858,46 +1860,6 @@ static void cdp_disable_all(void)
18581860
cdpl2_disable();
18591861
}
18601862

1861-
static int parse_rdtgroupfs_options(char *data)
1862-
{
1863-
char *token, *o = data;
1864-
int ret = 0;
1865-
1866-
while ((token = strsep(&o, ",")) != NULL) {
1867-
if (!*token) {
1868-
ret = -EINVAL;
1869-
goto out;
1870-
}
1871-
1872-
if (!strcmp(token, "cdp")) {
1873-
ret = cdpl3_enable();
1874-
if (ret)
1875-
goto out;
1876-
} else if (!strcmp(token, "cdpl2")) {
1877-
ret = cdpl2_enable();
1878-
if (ret)
1879-
goto out;
1880-
} else if (!strcmp(token, "mba_MBps")) {
1881-
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
1882-
ret = set_mba_sc(true);
1883-
else
1884-
ret = -EINVAL;
1885-
if (ret)
1886-
goto out;
1887-
} else {
1888-
ret = -EINVAL;
1889-
goto out;
1890-
}
1891-
}
1892-
1893-
return 0;
1894-
1895-
out:
1896-
pr_err("Invalid mount option \"%s\"\n", token);
1897-
1898-
return ret;
1899-
}
1900-
19011863
/*
19021864
* We don't allow rdtgroup directories to be created anywhere
19031865
* except the root directory. Thus when looking for the rdtgroup
@@ -1969,13 +1931,27 @@ static int mkdir_mondata_all(struct kernfs_node *parent_kn,
19691931
struct rdtgroup *prgrp,
19701932
struct kernfs_node **mon_data_kn);
19711933

1972-
static struct dentry *rdt_mount(struct file_system_type *fs_type,
1973-
int flags, const char *unused_dev_name,
1974-
void *data)
1934+
static int rdt_enable_ctx(struct rdt_fs_context *ctx)
1935+
{
1936+
int ret = 0;
1937+
1938+
if (ctx->enable_cdpl2)
1939+
ret = cdpl2_enable();
1940+
1941+
if (!ret && ctx->enable_cdpl3)
1942+
ret = cdpl3_enable();
1943+
1944+
if (!ret && ctx->enable_mba_mbps)
1945+
ret = set_mba_sc(true);
1946+
1947+
return ret;
1948+
}
1949+
1950+
static int rdt_get_tree(struct fs_context *fc)
19751951
{
1952+
struct rdt_fs_context *ctx = rdt_fc2context(fc);
19761953
struct rdt_domain *dom;
19771954
struct rdt_resource *r;
1978-
struct dentry *dentry;
19791955
int ret;
19801956

19811957
cpus_read_lock();
@@ -1984,53 +1960,42 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
19841960
* resctrl file system can only be mounted once.
19851961
*/
19861962
if (static_branch_unlikely(&rdt_enable_key)) {
1987-
dentry = ERR_PTR(-EBUSY);
1963+
ret = -EBUSY;
19881964
goto out;
19891965
}
19901966

1991-
ret = parse_rdtgroupfs_options(data);
1992-
if (ret) {
1993-
dentry = ERR_PTR(ret);
1967+
ret = rdt_enable_ctx(ctx);
1968+
if (ret < 0)
19941969
goto out_cdp;
1995-
}
19961970

19971971
closid_init();
19981972

19991973
ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
2000-
if (ret) {
2001-
dentry = ERR_PTR(ret);
2002-
goto out_cdp;
2003-
}
1974+
if (ret < 0)
1975+
goto out_mba;
20041976

20051977
if (rdt_mon_capable) {
20061978
ret = mongroup_create_dir(rdtgroup_default.kn,
20071979
NULL, "mon_groups",
20081980
&kn_mongrp);
2009-
if (ret) {
2010-
dentry = ERR_PTR(ret);
1981+
if (ret < 0)
20111982
goto out_info;
2012-
}
20131983
kernfs_get(kn_mongrp);
20141984

20151985
ret = mkdir_mondata_all(rdtgroup_default.kn,
20161986
&rdtgroup_default, &kn_mondata);
2017-
if (ret) {
2018-
dentry = ERR_PTR(ret);
1987+
if (ret < 0)
20191988
goto out_mongrp;
2020-
}
20211989
kernfs_get(kn_mondata);
20221990
rdtgroup_default.mon.mon_data_kn = kn_mondata;
20231991
}
20241992

20251993
ret = rdt_pseudo_lock_init();
2026-
if (ret) {
2027-
dentry = ERR_PTR(ret);
1994+
if (ret)
20281995
goto out_mondata;
2029-
}
20301996

2031-
dentry = kernfs_mount(fs_type, flags, rdt_root,
2032-
RDTGROUP_SUPER_MAGIC, NULL);
2033-
if (IS_ERR(dentry))
1997+
ret = kernfs_get_tree(fc);
1998+
if (ret < 0)
20341999
goto out_psl;
20352000

20362001
if (rdt_alloc_capable)
@@ -2059,14 +2024,95 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
20592024
kernfs_remove(kn_mongrp);
20602025
out_info:
20612026
kernfs_remove(kn_info);
2027+
out_mba:
2028+
if (ctx->enable_mba_mbps)
2029+
set_mba_sc(false);
20622030
out_cdp:
20632031
cdp_disable_all();
20642032
out:
20652033
rdt_last_cmd_clear();
20662034
mutex_unlock(&rdtgroup_mutex);
20672035
cpus_read_unlock();
2036+
return ret;
2037+
}
2038+
2039+
enum rdt_param {
2040+
Opt_cdp,
2041+
Opt_cdpl2,
2042+
Opt_mba_mpbs,
2043+
nr__rdt_params
2044+
};
2045+
2046+
static const struct fs_parameter_spec rdt_param_specs[] = {
2047+
fsparam_flag("cdp", Opt_cdp),
2048+
fsparam_flag("cdpl2", Opt_cdpl2),
2049+
fsparam_flag("mba_mpbs", Opt_mba_mpbs),
2050+
{}
2051+
};
2052+
2053+
static const struct fs_parameter_description rdt_fs_parameters = {
2054+
.name = "rdt",
2055+
.specs = rdt_param_specs,
2056+
};
2057+
2058+
static int rdt_parse_param(struct fs_context *fc, struct fs_parameter *param)
2059+
{
2060+
struct rdt_fs_context *ctx = rdt_fc2context(fc);
2061+
struct fs_parse_result result;
2062+
int opt;
2063+
2064+
opt = fs_parse(fc, &rdt_fs_parameters, param, &result);
2065+
if (opt < 0)
2066+
return opt;
20682067

2069-
return dentry;
2068+
switch (opt) {
2069+
case Opt_cdp:
2070+
ctx->enable_cdpl3 = true;
2071+
return 0;
2072+
case Opt_cdpl2:
2073+
ctx->enable_cdpl2 = true;
2074+
return 0;
2075+
case Opt_mba_mpbs:
2076+
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
2077+
return -EINVAL;
2078+
ctx->enable_mba_mbps = true;
2079+
return 0;
2080+
}
2081+
2082+
return -EINVAL;
2083+
}
2084+
2085+
static void rdt_fs_context_free(struct fs_context *fc)
2086+
{
2087+
struct rdt_fs_context *ctx = rdt_fc2context(fc);
2088+
2089+
kernfs_free_fs_context(fc);
2090+
kfree(ctx);
2091+
}
2092+
2093+
static const struct fs_context_operations rdt_fs_context_ops = {
2094+
.free = rdt_fs_context_free,
2095+
.parse_param = rdt_parse_param,
2096+
.get_tree = rdt_get_tree,
2097+
};
2098+
2099+
static int rdt_init_fs_context(struct fs_context *fc)
2100+
{
2101+
struct rdt_fs_context *ctx;
2102+
2103+
ctx = kzalloc(sizeof(struct rdt_fs_context), GFP_KERNEL);
2104+
if (!ctx)
2105+
return -ENOMEM;
2106+
2107+
ctx->kfc.root = rdt_root;
2108+
ctx->kfc.magic = RDTGROUP_SUPER_MAGIC;
2109+
fc->fs_private = &ctx->kfc;
2110+
fc->ops = &rdt_fs_context_ops;
2111+
if (fc->user_ns)
2112+
put_user_ns(fc->user_ns);
2113+
fc->user_ns = get_user_ns(&init_user_ns);
2114+
fc->global = true;
2115+
return 0;
20702116
}
20712117

20722118
static int reset_all_ctrls(struct rdt_resource *r)
@@ -2239,9 +2285,10 @@ static void rdt_kill_sb(struct super_block *sb)
22392285
}
22402286

22412287
static struct file_system_type rdt_fs_type = {
2242-
.name = "resctrl",
2243-
.mount = rdt_mount,
2244-
.kill_sb = rdt_kill_sb,
2288+
.name = "resctrl",
2289+
.init_fs_context = rdt_init_fs_context,
2290+
.parameters = &rdt_fs_parameters,
2291+
.kill_sb = rdt_kill_sb,
22452292
};
22462293

22472294
static int mon_addfile(struct kernfs_node *parent_kn, const char *name,

fs/kernfs/kernfs-internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/xattr.h>
1818

1919
#include <linux/kernfs.h>
20+
#include <linux/fs_context.h>
2021

2122
struct kernfs_iattrs {
2223
struct iattr ia_iattr;

0 commit comments

Comments
 (0)