mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06: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>
|
<optional>
|
||||||
<ref name="pm"/>
|
<ref name="pm"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="perf"/>
|
||||||
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<ref name="idmap"/>
|
<ref name="idmap"/>
|
||||||
</optional>
|
</optional>
|
||||||
@ -392,6 +395,30 @@
|
|||||||
</element>
|
</element>
|
||||||
</define>
|
</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:
|
The Identifiers can be:
|
||||||
- an optional id attribute with a number on the domain element
|
- 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->keywrap);
|
||||||
|
|
||||||
|
VIR_FREE(def->perf);
|
||||||
|
|
||||||
if (def->namespaceData && def->ns.free)
|
if (def->namespaceData && def->ns.free)
|
||||||
(def->ns.free)(def->namespaceData);
|
(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
|
static int
|
||||||
virDomainMemorySourceDefParseXML(xmlNodePtr node,
|
virDomainMemorySourceDefParseXML(xmlNodePtr node,
|
||||||
xmlXPathContextPtr ctxt,
|
xmlXPathContextPtr ctxt,
|
||||||
@ -15792,6 +15879,9 @@ virDomainDefParseXML(xmlDocPtr xml,
|
|||||||
&def->pm.s4) < 0)
|
&def->pm.s4) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (virDomainPerfDefParseXML(def, ctxt) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if ((tmp = virXPathString("string(./clock/@offset)", ctxt)) &&
|
if ((tmp = virXPathString("string(./clock/@offset)", ctxt)) &&
|
||||||
(def->clock.offset = virDomainClockOffsetTypeFromString(tmp)) < 0) {
|
(def->clock.offset = virDomainClockOffsetTypeFromString(tmp)) < 0) {
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
@ -21692,6 +21782,33 @@ virDomainKeyWrapDefFormat(virBufferPtr buf, virDomainKeyWrapDefPtr keywrap)
|
|||||||
virBufferAddLit(buf, "</keywrap>\n");
|
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
|
static bool
|
||||||
virDomainDefHasCapabilitiesFeatures(virDomainDefPtr def)
|
virDomainDefHasCapabilitiesFeatures(virDomainDefPtr def)
|
||||||
{
|
{
|
||||||
@ -22565,6 +22682,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
|||||||
virBufferAddLit(buf, "</pm>\n");
|
virBufferAddLit(buf, "</pm>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (def->perf)
|
||||||
|
virDomainPerfDefFormat(buf, def->perf);
|
||||||
|
|
||||||
virBufferAddLit(buf, "<devices>\n");
|
virBufferAddLit(buf, "<devices>\n");
|
||||||
virBufferAdjustIndent(buf, 2);
|
virBufferAdjustIndent(buf, 2);
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
# include "virseclabel.h"
|
# include "virseclabel.h"
|
||||||
# include "virprocess.h"
|
# include "virprocess.h"
|
||||||
# include "virgic.h"
|
# include "virgic.h"
|
||||||
|
# include "virperf.h"
|
||||||
|
|
||||||
/* forward declarations of all device types, required by
|
/* forward declarations of all device types, required by
|
||||||
* virDomainDeviceDef
|
* virDomainDeviceDef
|
||||||
@ -2187,6 +2188,13 @@ struct _virDomainPowerManagement {
|
|||||||
int s4;
|
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 struct _virDomainKeyWrapDef virDomainKeyWrapDef;
|
||||||
typedef virDomainKeyWrapDef *virDomainKeyWrapDefPtr;
|
typedef virDomainKeyWrapDef *virDomainKeyWrapDefPtr;
|
||||||
struct _virDomainKeyWrapDef {
|
struct _virDomainKeyWrapDef {
|
||||||
@ -2237,6 +2245,8 @@ struct _virDomainDef {
|
|||||||
|
|
||||||
virDomainPowerManagement pm;
|
virDomainPowerManagement pm;
|
||||||
|
|
||||||
|
virDomainPerfDefPtr perf;
|
||||||
|
|
||||||
virDomainOSDef os;
|
virDomainOSDef os;
|
||||||
char *emulator;
|
char *emulator;
|
||||||
/* These three options are of type virTristateSwitch,
|
/* These three options are of type virTristateSwitch,
|
||||||
|
@ -10042,9 +10042,14 @@ qemuDomainSetPerfEvents(virDomainPtr dom,
|
|||||||
virTypedParameterPtr params,
|
virTypedParameterPtr params,
|
||||||
int nparams)
|
int nparams)
|
||||||
{
|
{
|
||||||
|
virQEMUDriverPtr driver = dom->conn->privateData;
|
||||||
size_t i;
|
size_t i;
|
||||||
virDomainObjPtr vm = NULL;
|
virDomainObjPtr vm = NULL;
|
||||||
|
virQEMUDriverConfigPtr cfg = NULL;
|
||||||
qemuDomainObjPrivatePtr priv;
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
virDomainDefPtr def;
|
||||||
|
virDomainDefPtr persistentDef;
|
||||||
|
unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
virPerfEventType type;
|
virPerfEventType type;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
@ -10055,11 +10060,15 @@ qemuDomainSetPerfEvents(virDomainPtr dom,
|
|||||||
if (!(vm = qemuDomObjFromDomain(dom)))
|
if (!(vm = qemuDomObjFromDomain(dom)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
cfg = virQEMUDriverGetConfig(driver);
|
||||||
priv = vm->privateData;
|
priv = vm->privateData;
|
||||||
|
|
||||||
if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
|
if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
for (i = 0; i < nparams; i++) {
|
for (i = 0; i < nparams; i++) {
|
||||||
virTypedParameterPtr param = ¶ms[i];
|
virTypedParameterPtr param = ¶ms[i];
|
||||||
enabled = params->value.b;
|
enabled = params->value.b;
|
||||||
@ -10069,12 +10078,29 @@ qemuDomainSetPerfEvents(virDomainPtr dom,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (enabled && virPerfEventEnable(priv->perf, type, vm->pid))
|
if (enabled && virPerfEventEnable(priv->perf, type, vm->pid))
|
||||||
goto cleanup;
|
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;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
virDomainObjEndAPI(&vm);
|
virDomainObjEndAPI(&vm);
|
||||||
|
virObjectUnref(cfg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5127,6 +5127,7 @@ qemuProcessLaunch(virConnectPtr conn,
|
|||||||
virCapsPtr caps = NULL;
|
virCapsPtr caps = NULL;
|
||||||
size_t nnicindexes = 0;
|
size_t nnicindexes = 0;
|
||||||
int *nicindexes = NULL;
|
int *nicindexes = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
VIR_DEBUG("vm=%p name=%s id=%d asyncJob=%d "
|
VIR_DEBUG("vm=%p name=%s id=%d asyncJob=%d "
|
||||||
"incoming.launchURI=%s incoming.deferredURI=%s "
|
"incoming.launchURI=%s incoming.deferredURI=%s "
|
||||||
@ -5254,8 +5255,12 @@ qemuProcessLaunch(virConnectPtr conn,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
priv->perf = virPerfNew();
|
priv->perf = virPerfNew();
|
||||||
if (!priv->perf)
|
if (priv->perf) {
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This must be done after cgroup placement to avoid resetting CPU
|
/* This must be done after cgroup placement to avoid resetting CPU
|
||||||
* affinity */
|
* 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