mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
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:
parent
0dd0165c03
commit
afe833e9bd
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 = ¶ms[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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
20
tests/domainschemadata/domain-perf-simple.xml
Normal file
20
tests/domainschemadata/domain-perf-simple.xml
Normal 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>
|
Loading…
Reference in New Issue
Block a user