This patch adds new xml element, and so we can have the option of also having perf events enabled immediately at startup. Signed-off-by: Qiaowei Ren <qiaowei.ren@xxxxxxxxx> --- docs/schemas/domaincommon.rng | 27 +++++++ src/conf/domain_conf.c | 111 ++++++++++++++++++++++++++ src/conf/domain_conf.h | 10 +++ src/qemu/qemu_driver.c | 26 ++++++ src/qemu/qemu_process.c | 8 +- tests/domainschemadata/domain-perf-simple.xml | 20 +++++ 6 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 tests/domainschemadata/domain-perf-simple.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5deb17b..7f16620 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -56,6 +56,9 @@ <ref name="pm"/> </optional> <optional> + <ref name="perf"/> + </optional> + <optional> <ref name="idmap"/> </optional> <optional> @@ -393,6 +396,30 @@ </define> <!-- + Enable or disable perf events for the domain. For each + of the events the following rules apply: + on: the event will be forcefully enabled + off: the event will be forcefully disabled + not specified: the event will be disabled by default + --> + <define name="perf"> + <element name="perf"> + <oneOrMore> + <element name="event"> + <attribute name="name"> + <choice> + <value>cmt</value> + </choice> + </attribute> + <attribute name="enabled"> + <ref name="virYesNo"/> + </attribute> + </element> + </oneOrMore> + </element> + </define> + + <!-- The Identifiers can be: - an optional id attribute with a number on the domain element - a mandatory name diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1ea74a6..2e9201e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2580,6 +2580,8 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->keywrap); + VIR_FREE(def->perf); + if (def->namespaceData && def->ns.free) (def->ns.free)(def->namespaceData); @@ -12391,6 +12393,91 @@ virDomainPMStateParseXML(xmlXPathContextPtr ctxt, static int +virDomainPerfEventDefParseXML(virDomainPerfDefPtr perf, + xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + char *name = NULL; + char *enabled = NULL; + int enabled_type; + int name_type; + int ret = -1; + + xmlNodePtr oldnode = ctxt->node; + + ctxt->node = node; + if (!(name = virXPathString("string(./@name)", ctxt))) { + virReportError(VIR_ERR_CONF_SYNTAX, "%s", + _("missing name for event")); + goto cleanup; + } + + if ((name_type = virPerfEventTypeFromString(name)) < 0) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("%s is not a supported event name"), name); + goto cleanup; + } + + if (!(enabled = virXPathString("string(./@enabled)", ctxt))) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("missing state for cipher named %s"), name); + goto cleanup; + } + + if ((enabled_type = virTristateBoolTypeFromString(enabled)) < 0) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("%s is not a supported enabled state"), enabled); + goto cleanup; + } + + if (perf->events[VIR_PERF_EVENT_CMT] != VIR_TRISTATE_BOOL_ABSENT) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("A domain definition can have no more than " + "one event node with name %s"), + virTristateBoolTypeToString(name_type)); + + goto cleanup; + } + perf->events[VIR_PERF_EVENT_CMT] = enabled_type; + + ret = 0; + cleanup: + VIR_FREE(name); + VIR_FREE(enabled); + ctxt->node = oldnode; + return ret; +} + +static int +virDomainPerfDefParseXML(virDomainDefPtr def, + xmlXPathContextPtr ctxt) +{ + size_t i; + int ret = -1; + xmlNodePtr *nodes = NULL; + int n; + + if ((n = virXPathNodeSet("./perf/event", ctxt, &nodes)) < 0) + return n; + + if (VIR_ALLOC(def->perf) < 0) + goto cleanup; + + for (i = 0; i < n; i++) { + if (virDomainPerfEventDefParseXML(def->perf, nodes[i], ctxt) < 0) + goto cleanup; + } + + ret = 0; + + cleanup: + if (ret < 0) + VIR_FREE(def->perf); + VIR_FREE(nodes); + return ret; +} + +static int virDomainMemorySourceDefParseXML(xmlNodePtr node, xmlXPathContextPtr ctxt, virDomainMemoryDefPtr def) @@ -15643,6 +15730,9 @@ virDomainDefParseXML(xmlDocPtr xml, &def->pm.s4) < 0) goto error; + if (virDomainPerfDefParseXML(def, ctxt) < 0) + goto error; + if ((tmp = virXPathString("string(./clock/@offset)", ctxt)) && (def->clock.offset = virDomainClockOffsetTypeFromString(tmp)) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -21560,6 +21650,24 @@ virDomainKeyWrapDefFormat(virBufferPtr buf, virDomainKeyWrapDefPtr keywrap) virBufferAddLit(buf, "</keywrap>\n"); } +static void +virDomainPerfDefFormat(virBufferPtr buf, virDomainPerfDefPtr perf) +{ + size_t i; + virBufferAddLit(buf, "<perf>\n"); + virBufferAdjustIndent(buf, 2); + + for (i = 0; i < VIR_PERF_EVENT_LAST; i++) { + if (perf->events[i]) + virBufferAsprintf(buf, "<event name='%s' enabled='%s'/>\n", + virPerfEventTypeToString(i), + virTristateBoolTypeToString(perf->events[i])); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</perf>\n"); +} + static bool virDomainDefHasCapabilitiesFeatures(virDomainDefPtr def) { @@ -22264,6 +22372,9 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, "</pm>\n"); } + if (def->perf) + virDomainPerfDefFormat(buf, def->perf); + virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 0141009..7829750 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -50,6 +50,7 @@ # include "virstoragefile.h" # include "virseclabel.h" # include "virprocess.h" +# include "virperf.h" /* forward declarations of all device types, required by * virDomainDeviceDef @@ -2202,6 +2203,13 @@ struct _virDomainPowerManagement { int s4; }; +typedef struct _virDomainPerfDef virDomainPerfDef; +typedef virDomainPerfDef *virDomainPerfDefPtr; +struct _virDomainPerfDef { + /* These options are of type enum virTristateBool */ + int events[VIR_PERF_EVENT_LAST]; +}; + typedef struct _virDomainKeyWrapDef virDomainKeyWrapDef; typedef virDomainKeyWrapDef *virDomainKeyWrapDefPtr; struct _virDomainKeyWrapDef { @@ -2252,6 +2260,8 @@ struct _virDomainDef { virDomainPowerManagement pm; + virDomainPerfDefPtr perf; + virDomainOSDef os; char *emulator; /* These three options are of type virTristateSwitch, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 58d6015..a584716 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10325,9 +10325,14 @@ qemuDomainSetPerfEvents(virDomainPtr dom, virTypedParameterPtr params, int nparams) { + virQEMUDriverPtr driver = dom->conn->privateData; size_t i; virDomainObjPtr vm = NULL; + virQEMUDriverConfigPtr cfg = NULL; qemuDomainObjPrivatePtr priv; + virDomainDefPtr def; + virDomainDefPtr persistentDef; + unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT; int ret = -1; virPerfEventType type; bool enabled; @@ -10338,11 +10343,15 @@ qemuDomainSetPerfEvents(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; + cfg = virQEMUDriverGetConfig(driver); priv = vm->privateData; if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0) goto cleanup; + if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0) + goto cleanup; + for (i = 0; i < nparams; i++) { virTypedParameterPtr param = ¶ms[i]; enabled = params->value.b; @@ -10352,12 +10361,29 @@ qemuDomainSetPerfEvents(virDomainPtr dom, goto cleanup; if (enabled && virPerfEventEnable(priv->perf, type, vm->pid)) goto cleanup; + + if (def) { + def->perf->events[type] = enabled ? + VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO; + + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) + goto cleanup; + } + + if (persistentDef) { + persistentDef->perf->events[type] = enabled ? + VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO; + + if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0) + goto cleanup; + } } ret = 0; cleanup: virDomainObjEndAPI(&vm); + virObjectUnref(cfg); return ret; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index ae4b9ba..4595489 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4941,8 +4941,12 @@ qemuProcessLaunch(virConnectPtr conn, goto cleanup; priv->perf = virPerfNew(); - if (!priv->perf) - goto cleanup; + if (priv->perf) { + 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); + } + } /* This must be done after cgroup placement to avoid resetting CPU * affinity */ diff --git a/tests/domainschemadata/domain-perf-simple.xml b/tests/domainschemadata/domain-perf-simple.xml new file mode 100644 index 0000000..d7be7c9 --- /dev/null +++ b/tests/domainschemadata/domain-perf-simple.xml @@ -0,0 +1,20 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <perf> + <event name='cmt' enabled='yes'/> + </perf> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + </devices> +</domain> -- 1.9.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list