From: Qiaowei Ren <qiaowei.ren@xxxxxxxxx> 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@xxxxxxxxx> Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list