From: Qiaowei Ren <qiaowei.ren(a)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(a)intel.com>
Signed-off-by: John Ferlan <jferlan(a)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