Skip to content

Commit

Permalink
x86/intel_rdt: Add "info" files to resctrl file system
Browse files Browse the repository at this point in the history
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 <fenghua.yu@intel.com>
Cc: "Ravi V Shankar" <ravi.v.shankar@intel.com>
Cc: "Tony Luck" <tony.luck@intel.com>
Cc: "Shaohua Li" <shli@fb.com>
Cc: "Sai Prakhya" <sai.praneeth.prakhya@intel.com>
Cc: "Peter Zijlstra" <peterz@infradead.org>
Cc: "Stephane Eranian" <eranian@google.com>
Cc: "Dave Hansen" <dave.hansen@intel.com>
Cc: "David Carrillo-Cisneros" <davidcc@google.com>
Cc: "Nilay Vaish" <nilayvaish@gmail.com>
Cc: "Vikas Shivappa" <vikas.shivappa@linux.intel.com>
Cc: "Ingo Molnar" <mingo@elte.hu>
Cc: "Borislav Petkov" <bp@suse.de>
Cc: "H. Peter Anvin" <h.peter.anvin@intel.com>
Link: http://lkml.kernel.org/r/1477692289-37412-5-git-send-email-fenghua.yu@intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Fenghua Yu authored and Thomas Gleixner committed Oct 31, 2016
1 parent 5ff193f commit 4e978d0
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 0 deletions.
24 changes: 24 additions & 0 deletions arch/x86/include/asm/intel_rdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,30 @@ extern struct list_head rdt_all_groups;

int __init rdtgroup_init(void);

/**
* struct rftype - describe each file in the resctrl file system
* @name: file name
* @mode: access mode
* @kf_ops: operations
* @seq_show: show content of the file
* @write: write to the file
*/
struct rftype {
char *name;
umode_t mode;
struct kernfs_ops *kf_ops;

int (*seq_show)(struct kernfs_open_file *of,
struct seq_file *sf, void *v);
/*
* write() is the generic write callback which maps directly to
* kernfs write operation and overrides all other operations.
* Maximum write size is determined by ->max_write_len.
*/
ssize_t (*write)(struct kernfs_open_file *of,
char *buf, size_t nbytes, loff_t off);
};

/**
* struct rdt_resource - attributes of an RDT resource
* @enabled: Is this feature enabled on this machine
Expand Down
185 changes: 185 additions & 0 deletions arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/kernfs.h>
#include <linux/seq_file.h>
#include <linux/sched.h>
#include <linux/slab.h>

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

/* Kernel fs node for "info" directory under root */
static struct kernfs_node *kn_info;

/* set uid and gid of rdtgroup dirs and files to that of the creator */
static int rdtgroup_kn_set_ugid(struct kernfs_node *kn)
{
struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
.ia_uid = current_fsuid(),
.ia_gid = current_fsgid(), };

if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
return 0;

return kernfs_setattr(kn, &iattr);
}

static int rdtgroup_add_file(struct kernfs_node *parent_kn, struct rftype *rft)
{
struct kernfs_node *kn;
int ret;

kn = __kernfs_create_file(parent_kn, rft->name, rft->mode,
0, rft->kf_ops, rft, NULL, NULL);
if (IS_ERR(kn))
return PTR_ERR(kn);

ret = rdtgroup_kn_set_ugid(kn);
if (ret) {
kernfs_remove(kn);
return ret;
}

return 0;
}

static int rdtgroup_add_files(struct kernfs_node *kn, struct rftype *rfts,
int len)
{
struct rftype *rft;
int ret;

lockdep_assert_held(&rdtgroup_mutex);

for (rft = rfts; rft < rfts + len; rft++) {
ret = rdtgroup_add_file(kn, rft);
if (ret)
goto error;
}

return 0;
error:
pr_warn("Failed to add %s, err=%d\n", rft->name, ret);
while (--rft >= rfts)
kernfs_remove_by_name(kn, rft->name);
return ret;
}

static int rdtgroup_seqfile_show(struct seq_file *m, void *arg)
{
struct kernfs_open_file *of = m->private;
struct rftype *rft = of->kn->priv;

if (rft->seq_show)
return rft->seq_show(of, m, arg);
return 0;
}

static ssize_t rdtgroup_file_write(struct kernfs_open_file *of, char *buf,
size_t nbytes, loff_t off)
{
struct rftype *rft = of->kn->priv;

if (rft->write)
return rft->write(of, buf, nbytes, off);

return -EINVAL;
}

static struct kernfs_ops rdtgroup_kf_single_ops = {
.atomic_write_len = PAGE_SIZE,
.write = rdtgroup_file_write,
.seq_show = rdtgroup_seqfile_show,
};

static int rdt_num_closids_show(struct kernfs_open_file *of,
struct seq_file *seq, void *v)
{
struct rdt_resource *r = of->kn->parent->priv;

seq_printf(seq, "%d\n", r->num_closid);

return 0;
}

static int rdt_cbm_mask_show(struct kernfs_open_file *of,
struct seq_file *seq, void *v)
{
struct rdt_resource *r = of->kn->parent->priv;

seq_printf(seq, "%x\n", r->max_cbm);

return 0;
}

/* rdtgroup information files for one cache resource. */
static struct rftype res_info_files[] = {
{
.name = "num_closids",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_num_closids_show,
},
{
.name = "cbm_mask",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_cbm_mask_show,
},
};

static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
{
struct kernfs_node *kn_subdir;
struct rdt_resource *r;
int ret;

/* create the directory */
kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL);
if (IS_ERR(kn_info))
return PTR_ERR(kn_info);
kernfs_get(kn_info);

for_each_enabled_rdt_resource(r) {
kn_subdir = kernfs_create_dir(kn_info, r->name,
kn_info->mode, r);
if (IS_ERR(kn_subdir)) {
ret = PTR_ERR(kn_subdir);
goto out_destroy;
}
kernfs_get(kn_subdir);
ret = rdtgroup_kn_set_ugid(kn_subdir);
if (ret)
goto out_destroy;
ret = rdtgroup_add_files(kn_subdir, res_info_files,
ARRAY_SIZE(res_info_files));
if (ret)
goto out_destroy;
kernfs_activate(kn_subdir);
}

/*
* This extra ref will be put in kernfs_remove() and guarantees
* that @rdtgrp->kn is always accessible.
*/
kernfs_get(kn_info);

ret = rdtgroup_kn_set_ugid(kn_info);
if (ret)
goto out_destroy;

kernfs_activate(kn_info);

return 0;

out_destroy:
kernfs_remove(kn_info);
return ret;
}

static void l3_qos_cfg_update(void *arg)
{
bool *enable = arg;
Expand Down Expand Up @@ -137,6 +309,10 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
goto out_cdp;
}

ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
if (ret)
goto out_cdp;

dentry = kernfs_mount(fs_type, flags, rdt_root,
RDTGROUP_SUPER_MAGIC, NULL);
if (IS_ERR(dentry))
Expand Down Expand Up @@ -191,6 +367,14 @@ static int reset_all_cbms(struct rdt_resource *r)
return 0;
}

/*
* Forcibly remove all of subdirectories under root.
*/
static void rmdir_all_sub(void)
{
kernfs_remove(kn_info);
}

static void rdt_kill_sb(struct super_block *sb)
{
struct rdt_resource *r;
Expand All @@ -201,6 +385,7 @@ static void rdt_kill_sb(struct super_block *sb)
for_each_enabled_rdt_resource(r)
reset_all_cbms(r);
cdp_disable();
rmdir_all_sub();
static_branch_disable(&rdt_enable_key);
kernfs_kill_sb(sb);
mutex_unlock(&rdtgroup_mutex);
Expand Down

0 comments on commit 4e978d0

Please sign in to comment.