[libvirt] [PATCH v5 7/8] perf: Adjust the perf initialization

John Ferlan jferlan at redhat.com
Wed Aug 3 22:30:54 UTC 2016


From: Qiaowei Ren <qiaowei.ren at intel.com>

Introduce a static attr table and refactor virPerfEventEnable() for
general purpose usage.

This patch creates a static table/matrix that converts the VIR_PERF_EVENT_*
events into their respective "attr.type" and "attr.config" so that
virPerfEventEnable doesn't have the switch the calling function passes
by value the 'type'.

Signed-off-by: Qiaowei Ren <qiaowei.ren at intel.com>
Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/util/virperf.c | 164 +++++++++++++++++++++++++++++++++--------------------
 1 file changed, 103 insertions(+), 61 deletions(-)

diff --git a/src/util/virperf.c b/src/util/virperf.c
index 627b2ec..018000a 100644
--- a/src/util/virperf.c
+++ b/src/util/virperf.c
@@ -61,13 +61,24 @@ struct virPerf {
 
 # include <linux/perf_event.h>
 
-static virPerfEventPtr
-virPerfGetEvent(virPerfPtr perf,
-                virPerfEventType type)
-{
-    if (!perf)
-        return NULL;
+struct virPerfEventAttr {
+    int type;
+    unsigned int attrType;
+    unsigned long long attrConfig;
+};
+
+static struct virPerfEventAttr attrs[] = {
+    {.type = VIR_PERF_EVENT_CMT, .attrType = 0, .attrConfig = 1},
+    {.type = VIR_PERF_EVENT_MBMT, .attrType = 0, .attrConfig = 2},
+    {.type = VIR_PERF_EVENT_MBML, .attrType = 0, .attrConfig = 3},
+};
+typedef struct virPerfEventAttr *virPerfEventAttrPtr;
+
 
+static virPerfEventAttrPtr
+virPerfGetEventAttr(virPerfEventType type)
+{
+    size_t i;
     if (type >= VIR_PERF_EVENT_LAST) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Event '%d' is not supported"),
@@ -75,67 +86,113 @@ virPerfGetEvent(virPerfPtr perf,
         return NULL;
     }
 
-    return perf->events + type;
+    for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
+        if (i == type)
+            return attrs + i;
+    }
+
+    return NULL;
 }
 
+
 static int
-virPerfRdtEnable(virPerfEventPtr event,
-                 pid_t pid)
+virPerfRdtAttrInit(void)
 {
-    struct perf_event_attr rdt_attr;
     char *buf = NULL;
     char *tmp = NULL;
-    unsigned int event_type, scale;
+    unsigned int attr_type = 0;
 
-    if (virFileReadAll("/sys/devices/intel_cqm/type",
-                       10, &buf) < 0)
+    if (virFileReadAll("/sys/devices/intel_cqm/type", 10, &buf) < 0)
         goto error;
 
     if ((tmp = strchr(buf, '\n')))
         *tmp = '\0';
 
-    if (virStrToLong_ui(buf, NULL, 10, &event_type) < 0) {
+    if (virStrToLong_ui(buf, NULL, 10, &attr_type) < 0) {
         virReportSystemError(errno, "%s",
                              _("failed to get rdt event type"));
         goto error;
     }
     VIR_FREE(buf);
 
-    memset(&rdt_attr, 0, sizeof(rdt_attr));
-    rdt_attr.size = sizeof(rdt_attr);
-    rdt_attr.type = event_type;
-    rdt_attr.inherit = 1;
-    rdt_attr.disabled = 1;
-    rdt_attr.enable_on_exec = 0;
+    attrs[VIR_PERF_EVENT_CMT].attrType = attr_type;
+    attrs[VIR_PERF_EVENT_MBMT].attrType = attr_type;
+    attrs[VIR_PERF_EVENT_MBML].attrType = attr_type;
+
+    return 0;
+
+ error:
+    VIR_FREE(buf);
+    return -1;
+}
+
+
+static virPerfEventPtr
+virPerfGetEvent(virPerfPtr perf,
+                virPerfEventType type)
+{
+    if (!perf)
+        return NULL;
+
+    if (type >= VIR_PERF_EVENT_LAST) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Event '%d' is not supported"),
+                       type);
+        return NULL;
+    }
+
+    return perf->events + type;
+}
+
+int
+virPerfEventEnable(virPerfPtr perf,
+                   virPerfEventType type,
+                   pid_t pid)
+{
+    char *buf = NULL;
+    struct perf_event_attr attr;
+    virPerfEventPtr event = virPerfGetEvent(perf, type);
+    virPerfEventAttrPtr event_attr = virPerfGetEventAttr(type);
+
+    if (!event || !event_attr)
+        return -1;
 
-    switch (event->type) {
-    case VIR_PERF_EVENT_CMT:
+    if (event_attr->attrType == 0 && (type == VIR_PERF_EVENT_CMT ||
+                                       type == VIR_PERF_EVENT_MBMT ||
+                                       type == VIR_PERF_EVENT_MBML)) {
+        virReportSystemError(errno,
+                             _("Unable to open perf event for %s"),
+                             virPerfEventTypeToString(event->type));
+        return -1;
+    }
+
+    if (type == VIR_PERF_EVENT_CMT) {
         if (virFileReadAll("/sys/devices/intel_cqm/events/llc_occupancy.scale",
                            10, &buf) < 0)
             goto error;
 
-        if (virStrToLong_ui(buf, NULL, 10, &scale) < 0) {
+        if (virStrToLong_i(buf, NULL, 10, &event->efields.cmt.scale) < 0) {
             virReportSystemError(errno, "%s",
                                  _("failed to get cmt scaling factor"));
             goto error;
         }
-        event->efields.cmt.scale = scale;
-
-        rdt_attr.config = 1;
-        break;
-    case VIR_PERF_EVENT_MBMT:
-        rdt_attr.config = 2;
-        break;
-    case VIR_PERF_EVENT_MBML:
-        rdt_attr.config = 3;
-        break;
+
+        VIR_FREE(buf);
     }
 
-    event->fd = syscall(__NR_perf_event_open, &rdt_attr, pid, -1, -1, 0);
+    memset(&attr, 0, sizeof(attr));
+    attr.size = sizeof(attr);
+    attr.inherit = 1;
+    attr.disabled = 1;
+    attr.enable_on_exec = 0;
+    attr.type = event_attr->attrType;
+    attr.config = event_attr->attrConfig;
+
+    event->fd = syscall(__NR_perf_event_open, &attr, pid, -1, -1, 0);
     if (event->fd < 0) {
         virReportSystemError(errno,
-                             _("Unable to open perf type=%d for pid=%d"),
-                             event_type, pid);
+                             _("Unable to open perf event for %s"),
+                             virPerfEventTypeToString(event->type));
         goto error;
     }
 
@@ -156,31 +213,6 @@ virPerfRdtEnable(virPerfEventPtr event,
 }
 
 int
-virPerfEventEnable(virPerfPtr perf,
-                   virPerfEventType type,
-                   pid_t pid)
-{
-    virPerfEventPtr event = virPerfGetEvent(perf, type);
-    if (event == NULL)
-        return -1;
-
-    switch (type) {
-    case VIR_PERF_EVENT_CMT:
-    case VIR_PERF_EVENT_MBMT:
-    case VIR_PERF_EVENT_MBML:
-        if (virPerfRdtEnable(event, pid) < 0)
-            return -1;
-        break;
-    case VIR_PERF_EVENT_LAST:
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Unexpected perf event type=%d"), type);
-        return -1;
-    }
-
-    return 0;
-}
-
-int
 virPerfEventDisable(virPerfPtr perf,
                     virPerfEventType type)
 {
@@ -232,6 +264,13 @@ virPerfReadEvent(virPerfPtr perf,
 }
 
 #else
+static int
+virPerfRdtAttrInit(void)
+{
+    return 0;
+}
+
+
 int
 virPerfEventEnable(virPerfPtr perf ATTRIBUTE_UNUSED,
                    virPerfEventType type ATTRIBUTE_UNUSED,
@@ -285,6 +324,9 @@ virPerfNew(void)
         perf->events[i].enabled = false;
     }
 
+    if (virPerfRdtAttrInit() < 0)
+        virResetLastError();
+
     return perf;
 }
 
-- 
2.7.4




More information about the libvir-list mailing list