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@xxxxxxxxxxxxxxxxxx> --- 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 = ¶ms[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 = ¶ms[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, ¶ms, - &nparams, &maxparams) < 0) + if (enable && virshParseEventStr(enable, VIR_PERF_STATE_ENABLED, + ¶ms, &nparams, &maxparams) < 0) + goto cleanup; + + if (disable && virshParseEventStr(disable, VIR_PERF_STATE_DISABLED, + ¶ms, &nparams, &maxparams) < 0) goto cleanup; - if (disable && virshParseEventStr(disable, false, ¶ms, - &nparams, &maxparams) < 0) + if (resett && virshParseEventStr(resett, VIR_PERF_STATE_RESET, + ¶ms, &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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list