perf: add new xml element

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@intel.com>
Message-id: 1459171833-26416-6-git-send-email-qiaowei.ren@intel.com
This commit is contained in:
Qiaowei Ren 2016-03-28 21:30:30 +08:00 committed by Daniel P. Berrange
parent 0dd0165c03
commit afe833e9bd
6 changed files with 210 additions and 2 deletions

View File

@ -55,6 +55,9 @@
<optional>
<ref name="pm"/>
</optional>
<optional>
<ref name="perf"/>
</optional>
<optional>
<ref name="idmap"/>
</optional>
@ -392,6 +395,30 @@
</element>
</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

View File

@ -2642,6 +2642,8 @@ void virDomainDefFree(virDomainDefPtr def)
VIR_FREE(def->keywrap);
VIR_FREE(def->perf);
if (def->namespaceData && def->ns.free)
(def->ns.free)(def->namespaceData);
@ -12567,6 +12569,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,
@ -15792,6 +15879,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,
@ -21692,6 +21782,33 @@ virDomainKeyWrapDefFormat(virBufferPtr buf, virDomainKeyWrapDefPtr keywrap)
virBufferAddLit(buf, "</keywrap>\n");
}
static void
virDomainPerfDefFormat(virBufferPtr buf, virDomainPerfDefPtr perf)
{
size_t i;
bool wantPerf = false;
for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
if (perf->events[i])
wantPerf = true;
}
if (!wantPerf)
return;
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)
{
@ -22565,6 +22682,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virBufferAddLit(buf, "</pm>\n");
}
if (def->perf)
virDomainPerfDefFormat(buf, def->perf);
virBufferAddLit(buf, "<devices>\n");
virBufferAdjustIndent(buf, 2);

View File

@ -51,6 +51,7 @@
# include "virseclabel.h"
# include "virprocess.h"
# include "virgic.h"
# include "virperf.h"
/* forward declarations of all device types, required by
* virDomainDeviceDef
@ -2187,6 +2188,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 {
@ -2237,6 +2245,8 @@ struct _virDomainDef {
virDomainPowerManagement pm;
virDomainPerfDefPtr perf;
virDomainOSDef os;
char *emulator;
/* These three options are of type virTristateSwitch,

View File

@ -10042,9 +10042,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;
@ -10055,11 +10060,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 = &params[i];
enabled = params->value.b;
@ -10069,12 +10078,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, driver->caps) < 0)
goto cleanup;
}
if (persistentDef) {
persistentDef->perf->events[type] = enabled ?
VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
goto cleanup;
}
}
ret = 0;
cleanup:
virDomainObjEndAPI(&vm);
virObjectUnref(cfg);
return ret;
}

View File

@ -5127,6 +5127,7 @@ qemuProcessLaunch(virConnectPtr conn,
virCapsPtr caps = NULL;
size_t nnicindexes = 0;
int *nicindexes = NULL;
size_t i;
VIR_DEBUG("vm=%p name=%s id=%d asyncJob=%d "
"incoming.launchURI=%s incoming.deferredURI=%s "
@ -5254,8 +5255,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 */

View File

@ -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>