x86/intel_rdt: Add framework for better RDT UI diagnostics
authorTony Luck <tony.luck@intel.com>
Mon, 25 Sep 2017 23:39:33 +0000 (16:39 -0700)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 27 Sep 2017 10:10:10 +0000 (12:10 +0200)
Commands are given to the resctrl file system by making/removing
directories, or by writing to files.  When something goes wrong
the user is generally left wondering why they got:

   bash: echo: write error: Invalid argument

Add a new file "last_cmd_status" to the "info" directory that
will give the user some better clues on what went wrong.

Provide functions to clear and update last_cmd_status which
check that we hold the rdtgroup_mutex.

[ tglx: Made last_cmd_status static and folded back the hunk from patch 3
   which replaces the open coded access to last_cmd_status with the
   accessor function ]

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Vikas Shivappa <vikas.shivappa@intel.com>
Cc: Boris Petkov <bp@suse.de>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Link: https://lkml.kernel.org/r/edc4e0e9741eee89bba569f0021b1b2662fd9508.1506382469.git.tony.luck@intel.com
arch/x86/kernel/cpu/intel_rdt.h
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c

index ebaddae..9d3148d 100644 (file)
@@ -126,12 +126,15 @@ struct rdtgroup {
 #define RFTYPE_BASE                    BIT(1)
 #define RF_CTRLSHIFT                   4
 #define RF_MONSHIFT                    5
+#define RF_TOPSHIFT                    6
 #define RFTYPE_CTRL                    BIT(RF_CTRLSHIFT)
 #define RFTYPE_MON                     BIT(RF_MONSHIFT)
+#define RFTYPE_TOP                     BIT(RF_TOPSHIFT)
 #define RFTYPE_RES_CACHE               BIT(8)
 #define RFTYPE_RES_MB                  BIT(9)
 #define RF_CTRL_INFO                   (RFTYPE_INFO | RFTYPE_CTRL)
 #define RF_MON_INFO                    (RFTYPE_INFO | RFTYPE_MON)
+#define RF_TOP_INFO                    (RFTYPE_INFO | RFTYPE_TOP)
 #define RF_CTRL_BASE                   (RFTYPE_BASE | RFTYPE_CTRL)
 
 /* List of all resource groups */
@@ -408,6 +411,10 @@ union cpuid_0x10_x_edx {
        unsigned int full;
 };
 
+void rdt_last_cmd_clear(void);
+void rdt_last_cmd_puts(const char *s);
+void rdt_last_cmd_printf(const char *fmt, ...);
+
 void rdt_ctrl_update(void *arg);
 struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
 void rdtgroup_kn_unlock(struct kernfs_node *kn);
index a869d4a..6810351 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/kernfs.h>
+#include <linux/seq_buf.h>
 #include <linux/seq_file.h>
 #include <linux/sched/signal.h>
 #include <linux/sched/task.h>
@@ -51,6 +52,31 @@ static struct kernfs_node *kn_mongrp;
 /* Kernel fs node for "mon_data" directory under root */
 static struct kernfs_node *kn_mondata;
 
+static struct seq_buf last_cmd_status;
+static char last_cmd_status_buf[512];
+
+void rdt_last_cmd_clear(void)
+{
+       lockdep_assert_held(&rdtgroup_mutex);
+       seq_buf_clear(&last_cmd_status);
+}
+
+void rdt_last_cmd_puts(const char *s)
+{
+       lockdep_assert_held(&rdtgroup_mutex);
+       seq_buf_puts(&last_cmd_status, s);
+}
+
+void rdt_last_cmd_printf(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       lockdep_assert_held(&rdtgroup_mutex);
+       seq_buf_vprintf(&last_cmd_status, fmt, ap);
+       va_end(ap);
+}
+
 /*
  * Trivial allocator for CLOSIDs. Since h/w only supports a small number,
  * we can keep a bitmap of free CLOSIDs in a single integer.
@@ -569,6 +595,21 @@ static int rdtgroup_tasks_show(struct kernfs_open_file *of,
        return ret;
 }
 
+static int rdt_last_cmd_status_show(struct kernfs_open_file *of,
+                                   struct seq_file *seq, void *v)
+{
+       int len;
+
+       mutex_lock(&rdtgroup_mutex);
+       len = seq_buf_used(&last_cmd_status);
+       if (len)
+               seq_printf(seq, "%.*s", len, last_cmd_status_buf);
+       else
+               seq_puts(seq, "ok\n");
+       mutex_unlock(&rdtgroup_mutex);
+       return 0;
+}
+
 static int rdt_num_closids_show(struct kernfs_open_file *of,
                                struct seq_file *seq, void *v)
 {
@@ -686,6 +727,13 @@ static ssize_t max_threshold_occ_write(struct kernfs_open_file *of,
 /* rdtgroup information files for one cache resource. */
 static struct rftype res_common_files[] = {
        {
+               .name           = "last_cmd_status",
+               .mode           = 0444,
+               .kf_ops         = &rdtgroup_kf_single_ops,
+               .seq_show       = rdt_last_cmd_status_show,
+               .fflags         = RF_TOP_INFO,
+       },
+       {
                .name           = "num_closids",
                .mode           = 0444,
                .kf_ops         = &rdtgroup_kf_single_ops,
@@ -855,6 +903,10 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
                return PTR_ERR(kn_info);
        kernfs_get(kn_info);
 
+       ret = rdtgroup_add_files(kn_info, RF_TOP_INFO);
+       if (ret)
+               goto out_destroy;
+
        for_each_alloc_enabled_rdt_resource(r) {
                fflags =  r->fflags | RF_CTRL_INFO;
                ret = rdtgroup_mkdir_info_resdir(r, r->name, fflags);
@@ -1156,6 +1208,7 @@ out_info:
 out_cdp:
        cdp_disable();
 out:
+       rdt_last_cmd_clear();
        mutex_unlock(&rdtgroup_mutex);
 
        return dentry;
@@ -1902,6 +1955,9 @@ int __init rdtgroup_init(void)
 {
        int ret = 0;
 
+       seq_buf_init(&last_cmd_status, last_cmd_status_buf,
+                    sizeof(last_cmd_status_buf));
+
        ret = rdtgroup_setup_root();
        if (ret)
                return ret;