lkml.org 
[lkml]   [2016]   [Oct]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 12/18] x86/intel_rdt: Add "info" files to resctrl file system
    Date
    From: Fenghua Yu <fenghua.yu@intel.com>

    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>
    ---
    arch/x86/include/asm/intel_rdt.h | 24 ++++
    arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 186 +++++++++++++++++++++++++++++++
    2 files changed, 210 insertions(+)

    diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h
    index 8e1d002..39ed561 100644
    --- a/arch/x86/include/asm/intel_rdt.h
    +++ b/arch/x86/include/asm/intel_rdt.h
    @@ -25,6 +25,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
    * @capable: Is this feature available on this machine
    diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
    index 6c9061d..dd0d584 100644
    --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
    +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
    @@ -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>
    @@ -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("%s: failed to add %s, err=%d\n", __func__, 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_closid_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_val_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_closid",
    + .mode = 0444,
    + .kf_ops = &rdtgroup_kf_single_ops,
    + .seq_show = rdt_num_closid_show,
    + },
    + {
    + .name = "cbm_val",
    + .mode = 0444,
    + .kf_ops = &rdtgroup_kf_single_ops,
    + .seq_show = rdt_cbm_val_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 = *(bool *)arg;
    @@ -121,6 +293,10 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
    goto out;
    }

    + ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
    + if (ret)
    + goto out;
    +
    dentry = kernfs_mount(fs_type, flags, rdt_root,
    RDTGROUP_SUPER_MAGIC, NULL);
    if (IS_ERR(dentry))
    @@ -177,6 +353,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;
    @@ -194,6 +378,7 @@ static void rdt_kill_sb(struct super_block *sb)
    set_l3_qos_cfg(r, false);
    }

    + rmdir_all_sub();
    static_branch_disable(&rdt_enable_key);
    kernfs_kill_sb(sb);
    mutex_unlock(&rdtgroup_mutex);
    @@ -224,6 +409,7 @@ static int __init rdtgroup_setup_root(void)
    rdtgroup_default.kn = rdt_root->kn;
    kernfs_activate(rdtgroup_default.kn);

    +out:
    mutex_unlock(&rdtgroup_mutex);

    return 0;
    --
    2.5.0
    \
     
     \ /
      Last update: 2016-10-22 15:22    [W:2.668 / U:0.248 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site