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(a)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 = ¶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