[libvirt] [PATCH] perf: introduce option --reset

Nitesh Konkar niteshkonkar.libvirt at gmail.com
Mon Jan 23 10:33:21 UTC 2017


Currently you can either enable or disable a
perf event. This patch allows you to reset the
perf event using command line option --reset.
Eg: virsh perf domainName --reset cpu_cycles

Signed-off-by: Nitesh Konkar <nitkon12 at linux.vnet.ibm.com>
---
Example:
virsh domstats Fedora --perf
Domain: 'Fedora'

virsh  perf Fedora --enable cpu_cycles,cache_references
cpu_cycles     : enabled
cache_references: enabled

virsh domstats Fedora --perf
Domain: 'Fedora'
  perf.cpu_cycles=107559185
  perf.cache_references=563288

virsh perf Fedora --reset cache_misses,cpu_cycles,cache_references
cache_misses   : reset
cpu_cycles     : reset
cache_references: reset

virsh domstats Fedora --perf
Domain: 'Fedora'
  perf.cpu_cycles=0
  perf.cache_references=0
  perf.cache_misses=0

virsh perf Fedora --reset cache_misses,cpu_cycles,cache_references --config
error: Options --reset and --config are mutually exclusive

Should reset option be made available in the domainxml along with 
enabled=yes/no ? I have not included any such change in this patch as 
I think that there is no need to reset a perf counter as its value
for the VM's pid shall start by default at zero unless enabled.

 include/libvirt/libvirt-domain.h |  6 +++++
 src/libvirt_private.syms         |  1 +
 src/qemu/qemu_driver.c           | 52 ++++++++++++++++++++--------------------
 src/qemu/qemu_process.c          | 22 +++++++++++++----
 src/util/virperf.c               | 52 ++++++++++++++++++++++++++++------------
 src/util/virperf.h               | 12 ++++++----
 tools/virsh-domain.c             | 37 ++++++++++++++++++----------
 7 files changed, 120 insertions(+), 62 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index e303140..6072f00 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -2188,6 +2188,12 @@ void virDomainStatsRecordListFree(virDomainStatsRecordPtr *stats);
  */
 # define VIR_PERF_PARAM_REF_CPU_CYCLES "ref_cpu_cycles"
 
+enum {
+VIR_PERF_STATE_DISABLED,
+VIR_PERF_STATE_ENABLED,
+VIR_PERF_STATE_RESET,
+};
+
 int virDomainGetPerfEvents(virDomainPtr dom,
                            virTypedParameterPtr *params,
                            int *nparams,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cfeb43c..61bd207 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2229,6 +2229,7 @@ virPCIStubDriverTypeToString;
 virPerfEventDisable;
 virPerfEventEnable;
 virPerfEventIsEnabled;
+virPerfEventSetFd;
 virPerfEventTypeFromString;
 virPerfEventTypeToString;
 virPerfFree;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 516a851..8dd3ab7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9530,25 +9530,25 @@ qemuDomainSetPerfEvents(virDomainPtr dom,
     virDomainDefPtr persistentDef;
     int ret = -1;
     virPerfEventType type;
-    bool enabled;
+    int state;
 
     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                   VIR_DOMAIN_AFFECT_CONFIG, -1);
 
     if (virTypedParamsValidate(params, nparams,
-                               VIR_PERF_PARAM_CMT, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_MBMT, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_MBML, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_CACHE_REFERENCES, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_CACHE_MISSES, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_BRANCH_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_BRANCH_MISSES, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_BUS_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_STALLED_CYCLES_FRONTEND, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_STALLED_CYCLES_BACKEND, VIR_TYPED_PARAM_BOOLEAN,
-                               VIR_PERF_PARAM_REF_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
+                               VIR_PERF_PARAM_CMT, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_MBMT, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_MBML, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_CPU_CYCLES, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_INSTRUCTIONS, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_CACHE_REFERENCES, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_CACHE_MISSES, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_BRANCH_INSTRUCTIONS, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_BRANCH_MISSES, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_BUS_CYCLES, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_STALLED_CYCLES_FRONTEND, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_STALLED_CYCLES_BACKEND, VIR_TYPED_PARAM_INT,
+                               VIR_PERF_PARAM_REF_CPU_CYCLES, VIR_TYPED_PARAM_INT,
                                NULL) < 0)
         return -1;
 
@@ -9570,16 +9570,17 @@ qemuDomainSetPerfEvents(virDomainPtr dom,
     if (def) {
         for (i = 0; i < nparams; i++) {
             virTypedParameterPtr param = &params[i];
-            enabled = param->value.b;
+            state = param->value.i;
             type = virPerfEventTypeFromString(param->field);
 
-            if (!enabled && virPerfEventDisable(priv->perf, type) < 0)
-                goto endjob;
-            if (enabled && virPerfEventEnable(priv->perf, type, vm->pid) < 0)
+            if ((state == VIR_PERF_STATE_DISABLED) && virPerfEventDisable(priv->perf, type) < 0) {
                 goto endjob;
+            } else {
+                  if (virPerfEventSetFd(priv->perf, type, vm->pid, state) < 0)
+                    goto endjob;
+            }
 
-            def->perf.events[type] = enabled ?
-                VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
+            def->perf.events[type] = state;
         }
 
         if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
@@ -9589,11 +9590,10 @@ qemuDomainSetPerfEvents(virDomainPtr dom,
     if (persistentDef) {
         for (i = 0; i < nparams; i++) {
             virTypedParameterPtr param = &params[i];
-            enabled = param->value.b;
+            state = param->value.i;
             type = virPerfEventTypeFromString(param->field);
 
-            persistentDef->perf.events[type] = enabled ?
-                VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
+            persistentDef->perf.events[type] = state;
         }
 
         if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
@@ -9649,14 +9649,14 @@ qemuDomainGetPerfEvents(virDomainPtr dom,
     priv = vm->privateData;
 
     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
-        bool perf_enabled;
+        int perf_enabled;
 
         if (flags & VIR_DOMAIN_AFFECT_CONFIG)
-            perf_enabled = def->perf.events[i] == VIR_TRISTATE_BOOL_YES;
+            perf_enabled = def->perf.events[i];
         else
             perf_enabled = virPerfEventIsEnabled(priv->perf, i);
 
-        if (virTypedParamsAddBoolean(&par, &npar, &maxpar,
+        if (virTypedParamsAddInt(&par, &npar, &maxpar,
                                      virPerfEventTypeToString(i),
                                      perf_enabled) < 0)
             goto endjob;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 184440d..1bd7979 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3200,11 +3200,19 @@ qemuDomainPerfRestart(virDomainObjPtr vm)
 
     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
         if (def->perf.events[i] &&
-            def->perf.events[i] == VIR_TRISTATE_BOOL_YES) {
+            def->perf.events[i] == VIR_PERF_STATE_ENABLED) {
 
             /* Failure to re-enable the perf event should not be fatal */
-            if (virPerfEventEnable(priv->perf, i, vm->pid) < 0)
-                def->perf.events[i] = VIR_TRISTATE_BOOL_NO;
+            if (virPerfEventSetFd(priv->perf, i, vm->pid, VIR_PERF_STATE_ENABLED) < 0)
+                def->perf.events[i] = VIR_PERF_STATE_DISABLED;
+        }
+
+        if (def->perf.events[i] &&
+            def->perf.events[i] == VIR_PERF_STATE_RESET) {
+
+            /* Failure to reset the perf event should not be fatal */
+            if (virPerfEventSetFd(priv->perf, i, vm->pid, VIR_PERF_STATE_RESET) < 0)
+                def->perf.events[i] = VIR_PERF_STATE_DISABLED;
         }
     }
 
@@ -5563,8 +5571,12 @@ qemuProcessLaunch(virConnectPtr conn,
         goto cleanup;
 
     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
-        if (vm->def->perf.events[i] == VIR_TRISTATE_BOOL_YES &&
-            virPerfEventEnable(priv->perf, i, vm->pid) < 0)
+        if (vm->def->perf.events[i] == VIR_PERF_STATE_ENABLED &&
+            virPerfEventSetFd(priv->perf, i, vm->pid, VIR_PERF_STATE_ENABLED) < 0)
+            goto cleanup;
+
+        if (vm->def->perf.events[i] == VIR_PERF_STATE_RESET &&
+            virPerfEventSetFd(priv->perf, i, vm->pid, VIR_PERF_STATE_RESET) < 0)
             goto cleanup;
     }
 
diff --git a/src/util/virperf.c b/src/util/virperf.c
index f64692b..125166b 100644
--- a/src/util/virperf.c
+++ b/src/util/virperf.c
@@ -48,7 +48,7 @@ VIR_ENUM_IMPL(virPerfEvent, VIR_PERF_EVENT_LAST,
 struct virPerfEvent {
     int type;
     int fd;
-    bool enabled;
+    int state;
     union {
         /* cmt */
         struct {
@@ -186,9 +186,25 @@ virPerfGetEvent(virPerfPtr perf,
 }
 
 int
-virPerfEventEnable(virPerfPtr perf,
+virPerfEventEnable(int fd)
+{
+    if (ioctl(fd, PERF_EVENT_IOC_ENABLE) < 0)
+        return -1;
+    return 0;
+}
+
+int
+virPerfEventReset(int fd)
+{
+    if (ioctl(fd, PERF_EVENT_IOC_RESET) < 0)
+        return -1;
+    return 0;
+}
+
+int
+virPerfEventSetFd(virPerfPtr perf,
                    virPerfEventType type,
-                   pid_t pid)
+                   pid_t pid, int state)
 {
     char *buf = NULL;
     struct perf_event_attr attr;
@@ -237,14 +253,20 @@ virPerfEventEnable(virPerfPtr perf,
         goto error;
     }
 
-    if (ioctl(event->fd, PERF_EVENT_IOC_ENABLE) < 0) {
+    if (state == VIR_PERF_STATE_ENABLED && virPerfEventEnable(event->fd) < 0) {
         virReportSystemError(errno,
                              _("unable to enable host cpu perf event for %s"),
                              virPerfEventTypeToString(event->type));
         goto error;
     }
 
-    event->enabled = true;
+    if (state == VIR_PERF_STATE_RESET && virPerfEventReset(event->fd) < 0) {
+        virReportSystemError(errno,
+                             _("unable to reset host cpu perf event for %s"),
+                             virPerfEventTypeToString(event->type));
+        goto error;
+    }
+    event->state = state;
     return 0;
 
  error:
@@ -261,7 +283,7 @@ virPerfEventDisable(virPerfPtr perf,
     if (event == NULL)
         return -1;
 
-    if (!event->enabled)
+    if (!event->state)
         return 0;
 
     if (ioctl(event->fd, PERF_EVENT_IOC_DISABLE) < 0) {
@@ -271,19 +293,19 @@ virPerfEventDisable(virPerfPtr perf,
         return -1;
     }
 
-    event->enabled = false;
+    event->state = VIR_PERF_STATE_DISABLED;
     VIR_FORCE_CLOSE(event->fd);
     return 0;
 }
 
-bool virPerfEventIsEnabled(virPerfPtr perf,
+int virPerfEventIsEnabled(virPerfPtr perf,
                            virPerfEventType type)
 {
     virPerfEventPtr event = virPerfGetEvent(perf, type);
     if (event == NULL)
         return false;
 
-    return event->enabled;
+    return event->state;
 }
 
 int
@@ -292,7 +314,7 @@ virPerfReadEvent(virPerfPtr perf,
                  uint64_t *value)
 {
     virPerfEventPtr event = virPerfGetEvent(perf, type);
-    if (event == NULL || !event->enabled)
+    if (event == NULL || !event->state)
         return -1;
 
     if (saferead(event->fd, value, sizeof(uint64_t)) < 0) {
@@ -316,7 +338,7 @@ virPerfRdtAttrInit(void)
 
 
 int
-virPerfEventEnable(virPerfPtr perf ATTRIBUTE_UNUSED,
+virPerfEventSetFd(virPerfPtr perf ATTRIBUTE_UNUSED,
                    virPerfEventType type ATTRIBUTE_UNUSED,
                    pid_t pid ATTRIBUTE_UNUSED)
 {
@@ -334,11 +356,11 @@ virPerfEventDisable(virPerfPtr perf ATTRIBUTE_UNUSED,
     return -1;
 }
 
-bool
+int
 virPerfEventIsEnabled(virPerfPtr perf ATTRIBUTE_UNUSED,
                       virPerfEventType type ATTRIBUTE_UNUSED)
 {
-    return false;
+    return 0;
 }
 
 int
@@ -365,7 +387,7 @@ virPerfNew(void)
     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
         perf->events[i].type = i;
         perf->events[i].fd = -1;
-        perf->events[i].enabled = false;
+        perf->events[i].state = VIR_PERF_STATE_DISABLED;
     }
 
     if (virPerfRdtAttrInit() < 0)
@@ -383,7 +405,7 @@ virPerfFree(virPerfPtr perf)
         return;
 
     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
-        if (perf->events[i].enabled)
+        if (perf->events[i].state >= VIR_PERF_STATE_ENABLED)
             virPerfEventDisable(perf, i);
     }
 
diff --git a/src/util/virperf.h b/src/util/virperf.h
index 1f43c92..f79ef31 100644
--- a/src/util/virperf.h
+++ b/src/util/virperf.h
@@ -60,14 +60,18 @@ virPerfPtr virPerfNew(void);
 
 void virPerfFree(virPerfPtr perf);
 
-int virPerfEventEnable(virPerfPtr perf,
-                       virPerfEventType type,
-                       pid_t pid);
+int virPerfEventSetFd(virPerfPtr perf,
+                      virPerfEventType type,
+                      pid_t pid, int state);
+
+int virPerfEventEnable(int fd);
+
+int virPerfEventReset(int fd);
 
 int virPerfEventDisable(virPerfPtr perf,
                         virPerfEventType type);
 
-bool virPerfEventIsEnabled(virPerfPtr perf,
+int virPerfEventIsEnabled(virPerfPtr perf,
                            virPerfEventType type);
 
 int virPerfReadEvent(virPerfPtr perf,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 93587e8..806490b 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -8794,7 +8794,7 @@ cmdMemtune(vshControl *ctl, const vshCmd *cmd)
  */
 static const vshCmdInfo info_perf[] = {
     {.name = "help",
-        .data = N_("Get or set perf event")
+        .data = N_("Get, set or reset perf event")
     },
     {.name = "desc",
         .data = N_("Get or set the current perf events for a guest"
@@ -8815,6 +8815,10 @@ static const vshCmdOptDef opts_perf[] = {
      .type = VSH_OT_STRING,
      .help = N_("perf events which will be disabled")
     },
+    {.name = "reset",
+     .type = VSH_OT_STRING,
+     .help = N_("perf events which will be reset")
+    },
     VIRSH_COMMON_OPT_DOMAIN_CONFIG,
     VIRSH_COMMON_OPT_DOMAIN_LIVE,
     VIRSH_COMMON_OPT_DOMAIN_CURRENT,
@@ -8823,7 +8827,7 @@ static const vshCmdOptDef opts_perf[] = {
 
 static int
 virshParseEventStr(const char *event,
-                   bool state,
+                   int state,
                    virTypedParameterPtr *params,
                    int *nparams,
                    int *maxparams)
@@ -8837,7 +8841,7 @@ virshParseEventStr(const char *event,
 
     for (i = 0; i < ntok; i++) {
         if ((*tok[i] != '\0') &&
-            virTypedParamsAddBoolean(params, nparams,
+            virTypedParamsAddInt(params, nparams,
                                      maxparams, tok[i], state) < 0)
             goto cleanup;
     }
@@ -8854,9 +8858,11 @@ virshPrintPerfStatus(vshControl *ctl, virTypedParameterPtr params, int nparams)
     size_t i;
 
     for (i = 0; i < nparams; i++) {
-        if (params[i].type == VIR_TYPED_PARAM_BOOLEAN &&
-            params[i].value.b) {
+        if (params[i].type == VIR_TYPED_PARAM_INT &&
+            params[i].value.i == VIR_PERF_STATE_ENABLED) {
             vshPrintExtra(ctl, "%-15s: %s\n", params[i].field, _("enabled"));
+        } else if (params[i].value.i == VIR_PERF_STATE_RESET) {
+                vshPrintExtra(ctl, "%-15s: %s\n", params[i].field, _("reset"));
         } else {
             vshPrintExtra(ctl, "%-15s: %s\n", params[i].field, _("disabled"));
         }
@@ -8871,14 +8877,16 @@ cmdPerf(vshControl *ctl, const vshCmd *cmd)
     int maxparams = 0;
     virTypedParameterPtr params = NULL;
     bool ret = false;
-    const char *enable = NULL, *disable = NULL;
+    const char *enable = NULL, *disable = NULL, *resett = NULL;
     unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
     bool current = vshCommandOptBool(cmd, "current");
     bool config = vshCommandOptBool(cmd, "config");
     bool live = vshCommandOptBool(cmd, "live");
+    bool reset = vshCommandOptBool(cmd, "reset");
 
     VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
     VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+    VSH_EXCLUSIVE_OPTIONS_VAR(reset, config);
 
     if (config)
         flags |= VIR_DOMAIN_AFFECT_CONFIG;
@@ -8886,18 +8894,23 @@ cmdPerf(vshControl *ctl, const vshCmd *cmd)
         flags |= VIR_DOMAIN_AFFECT_LIVE;
 
     if (vshCommandOptStringReq(ctl, cmd, "enable", &enable) < 0 ||
-        vshCommandOptStringReq(ctl, cmd, "disable", &disable) < 0)
+        vshCommandOptStringReq(ctl, cmd, "disable", &disable) < 0 ||
+        vshCommandOptStringReq(ctl, cmd, "reset", &resett) < 0)
         return false;
 
     if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
         return false;
 
-    if (enable && virshParseEventStr(enable, true, &params,
-                                     &nparams, &maxparams) < 0)
+    if (enable && virshParseEventStr(enable, VIR_PERF_STATE_ENABLED,
+                                     &params, &nparams, &maxparams) < 0)
+        goto cleanup;
+
+    if (disable && virshParseEventStr(disable, VIR_PERF_STATE_DISABLED,
+                                      &params, &nparams, &maxparams) < 0)
         goto cleanup;
 
-    if (disable && virshParseEventStr(disable, false, &params,
-                                      &nparams, &maxparams) < 0)
+    if (resett && virshParseEventStr(resett, VIR_PERF_STATE_RESET,
+                                    &params, &nparams, &maxparams) < 0)
         goto cleanup;
 
     if (nparams == 0) {
@@ -8908,7 +8921,7 @@ cmdPerf(vshControl *ctl, const vshCmd *cmd)
         virshPrintPerfStatus(ctl, params, nparams);
     } else {
         if (virDomainSetPerfEvents(dom, params, nparams, flags) != 0) {
-            vshError(ctl, "%s", _("Unable to enable/disable perf events"));
+            vshError(ctl, "%s", _("Unable to enable/disable/reset perf events"));
             goto cleanup;
         } else {
             virshPrintPerfStatus(ctl, params, nparams);
-- 
1.9.3




More information about the libvir-list mailing list