Skip to content

Commit 4e978d0

Browse files
Fenghua YuKAGA-KOKO
authored andcommitted
x86/intel_rdt: Add "info" files to resctrl file system
For the convenience of applications we make the decoded values of some of the CPUID values available in read-only (0444) files. Signed-off-by: Fenghua Yu <[email protected]> Cc: "Ravi V Shankar" <[email protected]> Cc: "Tony Luck" <[email protected]> Cc: "Shaohua Li" <[email protected]> Cc: "Sai Prakhya" <[email protected]> Cc: "Peter Zijlstra" <[email protected]> Cc: "Stephane Eranian" <[email protected]> Cc: "Dave Hansen" <[email protected]> Cc: "David Carrillo-Cisneros" <[email protected]> Cc: "Nilay Vaish" <[email protected]> Cc: "Vikas Shivappa" <[email protected]> Cc: "Ingo Molnar" <[email protected]> Cc: "Borislav Petkov" <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 5ff193f commit 4e978d0

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

arch/x86/include/asm/intel_rdt.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,30 @@ extern struct list_head rdt_all_groups;
2626

2727
int __init rdtgroup_init(void);
2828

29+
/**
30+
* struct rftype - describe each file in the resctrl file system
31+
* @name: file name
32+
* @mode: access mode
33+
* @kf_ops: operations
34+
* @seq_show: show content of the file
35+
* @write: write to the file
36+
*/
37+
struct rftype {
38+
char *name;
39+
umode_t mode;
40+
struct kernfs_ops *kf_ops;
41+
42+
int (*seq_show)(struct kernfs_open_file *of,
43+
struct seq_file *sf, void *v);
44+
/*
45+
* write() is the generic write callback which maps directly to
46+
* kernfs write operation and overrides all other operations.
47+
* Maximum write size is determined by ->max_write_len.
48+
*/
49+
ssize_t (*write)(struct kernfs_open_file *of,
50+
char *buf, size_t nbytes, loff_t off);
51+
};
52+
2953
/**
3054
* struct rdt_resource - attributes of an RDT resource
3155
* @enabled: Is this feature enabled on this machine

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <linux/fs.h>
2424
#include <linux/sysfs.h>
2525
#include <linux/kernfs.h>
26+
#include <linux/seq_file.h>
27+
#include <linux/sched.h>
2628
#include <linux/slab.h>
2729

2830
#include <uapi/linux/magic.h>
@@ -34,6 +36,176 @@ struct kernfs_root *rdt_root;
3436
struct rdtgroup rdtgroup_default;
3537
LIST_HEAD(rdt_all_groups);
3638

39+
/* Kernel fs node for "info" directory under root */
40+
static struct kernfs_node *kn_info;
41+
42+
/* set uid and gid of rdtgroup dirs and files to that of the creator */
43+
static int rdtgroup_kn_set_ugid(struct kernfs_node *kn)
44+
{
45+
struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
46+
.ia_uid = current_fsuid(),
47+
.ia_gid = current_fsgid(), };
48+
49+
if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
50+
gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
51+
return 0;
52+
53+
return kernfs_setattr(kn, &iattr);
54+
}
55+
56+
static int rdtgroup_add_file(struct kernfs_node *parent_kn, struct rftype *rft)
57+
{
58+
struct kernfs_node *kn;
59+
int ret;
60+
61+
kn = __kernfs_create_file(parent_kn, rft->name, rft->mode,
62+
0, rft->kf_ops, rft, NULL, NULL);
63+
if (IS_ERR(kn))
64+
return PTR_ERR(kn);
65+
66+
ret = rdtgroup_kn_set_ugid(kn);
67+
if (ret) {
68+
kernfs_remove(kn);
69+
return ret;
70+
}
71+
72+
return 0;
73+
}
74+
75+
static int rdtgroup_add_files(struct kernfs_node *kn, struct rftype *rfts,
76+
int len)
77+
{
78+
struct rftype *rft;
79+
int ret;
80+
81+
lockdep_assert_held(&rdtgroup_mutex);
82+
83+
for (rft = rfts; rft < rfts + len; rft++) {
84+
ret = rdtgroup_add_file(kn, rft);
85+
if (ret)
86+
goto error;
87+
}
88+
89+
return 0;
90+
error:
91+
pr_warn("Failed to add %s, err=%d\n", rft->name, ret);
92+
while (--rft >= rfts)
93+
kernfs_remove_by_name(kn, rft->name);
94+
return ret;
95+
}
96+
97+
static int rdtgroup_seqfile_show(struct seq_file *m, void *arg)
98+
{
99+
struct kernfs_open_file *of = m->private;
100+
struct rftype *rft = of->kn->priv;
101+
102+
if (rft->seq_show)
103+
return rft->seq_show(of, m, arg);
104+
return 0;
105+
}
106+
107+
static ssize_t rdtgroup_file_write(struct kernfs_open_file *of, char *buf,
108+
size_t nbytes, loff_t off)
109+
{
110+
struct rftype *rft = of->kn->priv;
111+
112+
if (rft->write)
113+
return rft->write(of, buf, nbytes, off);
114+
115+
return -EINVAL;
116+
}
117+
118+
static struct kernfs_ops rdtgroup_kf_single_ops = {
119+
.atomic_write_len = PAGE_SIZE,
120+
.write = rdtgroup_file_write,
121+
.seq_show = rdtgroup_seqfile_show,
122+
};
123+
124+
static int rdt_num_closids_show(struct kernfs_open_file *of,
125+
struct seq_file *seq, void *v)
126+
{
127+
struct rdt_resource *r = of->kn->parent->priv;
128+
129+
seq_printf(seq, "%d\n", r->num_closid);
130+
131+
return 0;
132+
}
133+
134+
static int rdt_cbm_mask_show(struct kernfs_open_file *of,
135+
struct seq_file *seq, void *v)
136+
{
137+
struct rdt_resource *r = of->kn->parent->priv;
138+
139+
seq_printf(seq, "%x\n", r->max_cbm);
140+
141+
return 0;
142+
}
143+
144+
/* rdtgroup information files for one cache resource. */
145+
static struct rftype res_info_files[] = {
146+
{
147+
.name = "num_closids",
148+
.mode = 0444,
149+
.kf_ops = &rdtgroup_kf_single_ops,
150+
.seq_show = rdt_num_closids_show,
151+
},
152+
{
153+
.name = "cbm_mask",
154+
.mode = 0444,
155+
.kf_ops = &rdtgroup_kf_single_ops,
156+
.seq_show = rdt_cbm_mask_show,
157+
},
158+
};
159+
160+
static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
161+
{
162+
struct kernfs_node *kn_subdir;
163+
struct rdt_resource *r;
164+
int ret;
165+
166+
/* create the directory */
167+
kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL);
168+
if (IS_ERR(kn_info))
169+
return PTR_ERR(kn_info);
170+
kernfs_get(kn_info);
171+
172+
for_each_enabled_rdt_resource(r) {
173+
kn_subdir = kernfs_create_dir(kn_info, r->name,
174+
kn_info->mode, r);
175+
if (IS_ERR(kn_subdir)) {
176+
ret = PTR_ERR(kn_subdir);
177+
goto out_destroy;
178+
}
179+
kernfs_get(kn_subdir);
180+
ret = rdtgroup_kn_set_ugid(kn_subdir);
181+
if (ret)
182+
goto out_destroy;
183+
ret = rdtgroup_add_files(kn_subdir, res_info_files,
184+
ARRAY_SIZE(res_info_files));
185+
if (ret)
186+
goto out_destroy;
187+
kernfs_activate(kn_subdir);
188+
}
189+
190+
/*
191+
* This extra ref will be put in kernfs_remove() and guarantees
192+
* that @rdtgrp->kn is always accessible.
193+
*/
194+
kernfs_get(kn_info);
195+
196+
ret = rdtgroup_kn_set_ugid(kn_info);
197+
if (ret)
198+
goto out_destroy;
199+
200+
kernfs_activate(kn_info);
201+
202+
return 0;
203+
204+
out_destroy:
205+
kernfs_remove(kn_info);
206+
return ret;
207+
}
208+
37209
static void l3_qos_cfg_update(void *arg)
38210
{
39211
bool *enable = arg;
@@ -137,6 +309,10 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
137309
goto out_cdp;
138310
}
139311

312+
ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
313+
if (ret)
314+
goto out_cdp;
315+
140316
dentry = kernfs_mount(fs_type, flags, rdt_root,
141317
RDTGROUP_SUPER_MAGIC, NULL);
142318
if (IS_ERR(dentry))
@@ -191,6 +367,14 @@ static int reset_all_cbms(struct rdt_resource *r)
191367
return 0;
192368
}
193369

370+
/*
371+
* Forcibly remove all of subdirectories under root.
372+
*/
373+
static void rmdir_all_sub(void)
374+
{
375+
kernfs_remove(kn_info);
376+
}
377+
194378
static void rdt_kill_sb(struct super_block *sb)
195379
{
196380
struct rdt_resource *r;
@@ -201,6 +385,7 @@ static void rdt_kill_sb(struct super_block *sb)
201385
for_each_enabled_rdt_resource(r)
202386
reset_all_cbms(r);
203387
cdp_disable();
388+
rmdir_all_sub();
204389
static_branch_disable(&rdt_enable_key);
205390
kernfs_kill_sb(sb);
206391
mutex_unlock(&rdtgroup_mutex);

0 commit comments

Comments
 (0)