[PATCH v6 04/10] x86/intel_rdt: Add "info" files to resctrl file system

2016-10-28 Thread Fenghua Yu
From: Fenghua Yu 

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 
---
 arch/x86/include/asm/intel_rdt.h |  24 
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 185 +++
 2 files changed, 209 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 74d7f72f..58aa8f7 100644
--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
+++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
@@ -23,6 +23,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 #include 
@@ -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, );
+}
+
+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(_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;
+
+ 

[PATCH v6 04/10] x86/intel_rdt: Add "info" files to resctrl file system

2016-10-28 Thread Fenghua Yu
From: Fenghua Yu 

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 
---
 arch/x86/include/asm/intel_rdt.h |  24 
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 185 +++
 2 files changed, 209 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 74d7f72f..58aa8f7 100644
--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
+++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
@@ -23,6 +23,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 #include 
@@ -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, );
+}
+
+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(_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);