conf: Add support for memorytune XML processing for resctrl MBA
Introduce a new section memorytune to support memory bandwidth allocation. This is consistent with existing cachetune. As the example: below: <cputune> ...... <memorytune vcpus='0'> <node id='0' bandwidth='30'/> </memorytune> </cputune> vpus --- vpus subjected to this memory bandwidth. id --- on which node memory bandwidth to be set. bandwidth --- the memory bandwidth percent to set. Signed-off-by: Bing Niu <bing.niu@intel.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
72824f67cd
commit
6956b7eedc
@ -759,6 +759,10 @@
|
|||||||
<cache id='0' level='3' type='both' size='3' unit='MiB'/>
|
<cache id='0' level='3' type='both' size='3' unit='MiB'/>
|
||||||
<cache id='1' level='3' type='both' size='3' unit='MiB'/>
|
<cache id='1' level='3' type='both' size='3' unit='MiB'/>
|
||||||
</cachetune>
|
</cachetune>
|
||||||
|
<memorytune vcpus='0-3'>
|
||||||
|
<node id='0' bandwidth='60'/>
|
||||||
|
</memorytune>
|
||||||
|
|
||||||
</cputune>
|
</cputune>
|
||||||
...
|
...
|
||||||
</domain>
|
</domain>
|
||||||
@ -932,7 +936,9 @@
|
|||||||
size and required granularity are reported as well. The required
|
size and required granularity are reported as well. The required
|
||||||
attribute <code>vcpus</code> specifies to which vCPUs this allocation
|
attribute <code>vcpus</code> specifies to which vCPUs this allocation
|
||||||
applies. A vCPU can only be member of one <code>cachetune</code> element
|
applies. A vCPU can only be member of one <code>cachetune</code> element
|
||||||
allocations. Supported subelements are:
|
allocation. The vCPUs specified by cachetune can be identical with those
|
||||||
|
in memorytune, however they are not allowed to overlap.
|
||||||
|
Supported subelements are:
|
||||||
<dl>
|
<dl>
|
||||||
<dt><code>cache</code></dt>
|
<dt><code>cache</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
@ -972,7 +978,38 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt><code>memorytune</code><span class="since">Since 4.7.0</span></dt>
|
||||||
|
<dd>
|
||||||
|
Optional <code>memorytune</code> element can control allocations for
|
||||||
|
memory bandwidth using the resctrl on the host. Whether or not is this
|
||||||
|
supported can be gathered from capabilities where some limitations like
|
||||||
|
minimum bandwidth and required granularity are reported as well. The
|
||||||
|
required attribute <code>vcpus</code> specifies to which vCPUs this
|
||||||
|
allocation applies. A vCPU can only be member of one
|
||||||
|
<code>memorytune</code> element allocation. The <code>vcpus</code> specified
|
||||||
|
by <code>memorytune</code> can be identical to those specified by
|
||||||
|
<code>cachetune</code>. However they are not allowed to overlap each other.
|
||||||
|
Supported subelements are:
|
||||||
|
<dl>
|
||||||
|
<dt><code>node</code></dt>
|
||||||
|
<dd>
|
||||||
|
This element controls the allocation of CPU memory bandwidth and has the
|
||||||
|
following attributes:
|
||||||
|
<dl>
|
||||||
|
<dt><code>id</code></dt>
|
||||||
|
<dd>
|
||||||
|
Host node id from which to allocate memory bandwidth.
|
||||||
|
</dd>
|
||||||
|
<dt><code>bandwidth</code></dt>
|
||||||
|
<dd>
|
||||||
|
The memory bandwidth to allocate from this node. The value by default
|
||||||
|
is in percentage.
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
@ -983,6 +983,23 @@
|
|||||||
</oneOrMore>
|
</oneOrMore>
|
||||||
</element>
|
</element>
|
||||||
</zeroOrMore>
|
</zeroOrMore>
|
||||||
|
<zeroOrMore>
|
||||||
|
<element name="memorytune">
|
||||||
|
<attribute name="vcpus">
|
||||||
|
<ref name='cpuset'/>
|
||||||
|
</attribute>
|
||||||
|
<oneOrMore>
|
||||||
|
<element name="node">
|
||||||
|
<attribute name="id">
|
||||||
|
<ref name='unsignedInt'/>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="bandwidth">
|
||||||
|
<ref name='unsignedInt'/>
|
||||||
|
</attribute>
|
||||||
|
</element>
|
||||||
|
</oneOrMore>
|
||||||
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
</interleave>
|
</interleave>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
@ -19418,6 +19418,129 @@ virDomainDefParseCaps(virDomainDefPtr def,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
virResctrlAllocPtr alloc)
|
||||||
|
{
|
||||||
|
xmlNodePtr oldnode = ctxt->node;
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int bandwidth;
|
||||||
|
char *tmp = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
ctxt->node = node;
|
||||||
|
|
||||||
|
tmp = virXMLPropString(node, "id");
|
||||||
|
if (!tmp) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Missing memorytune attribute 'id'"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (virStrToLong_uip(tmp, NULL, 10, &id) < 0) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("Invalid memorytune attribute 'id' value '%s'"),
|
||||||
|
tmp);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
|
||||||
|
tmp = virXMLPropString(node, "bandwidth");
|
||||||
|
if (!tmp) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Missing memorytune attribute 'bandwidth'"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (virStrToLong_uip(tmp, NULL, 10, &bandwidth) < 0) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("Invalid memorytune attribute 'bandwidth' value '%s'"),
|
||||||
|
tmp);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
if (virResctrlAllocSetMemoryBandwidth(alloc, id, bandwidth) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
ctxt->node = oldnode;
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainMemorytuneDefParse(virDomainDefPtr def,
|
||||||
|
xmlXPathContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
xmlNodePtr oldnode = ctxt->node;
|
||||||
|
xmlNodePtr *nodes = NULL;
|
||||||
|
virBitmapPtr vcpus = NULL;
|
||||||
|
virResctrlAllocPtr alloc = NULL;
|
||||||
|
ssize_t i = 0;
|
||||||
|
int n;
|
||||||
|
int ret = -1;
|
||||||
|
bool new_alloc = false;
|
||||||
|
|
||||||
|
ctxt->node = node;
|
||||||
|
|
||||||
|
if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virBitmapIsAllClear(vcpus)) {
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((n = virXPathNodeSet("./node", ctxt, &nodes)) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Cannot extract memory nodes under memorytune"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virDomainResctrlVcpuMatch(def, vcpus, &alloc) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!alloc) {
|
||||||
|
alloc = virResctrlAllocNew();
|
||||||
|
if (!alloc)
|
||||||
|
goto cleanup;
|
||||||
|
new_alloc = true;
|
||||||
|
} else {
|
||||||
|
alloc = virObjectRef(alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (virDomainMemorytuneDefParseMemory(ctxt, nodes[i], alloc) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (virResctrlAllocIsEmpty(alloc)) {
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If this is a new allocation, format ID and append to resctrl, otherwise
|
||||||
|
* just update the existing alloc information, which is done in above
|
||||||
|
* virDomainMemorytuneDefParseMemory */
|
||||||
|
if (new_alloc) {
|
||||||
|
if (virDomainResctrlAppend(def, node, alloc, vcpus, flags) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
vcpus = NULL;
|
||||||
|
alloc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
ctxt->node = oldnode;
|
||||||
|
virObjectUnref(alloc);
|
||||||
|
virBitmapFree(vcpus);
|
||||||
|
VIR_FREE(nodes);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virDomainDefPtr
|
static virDomainDefPtr
|
||||||
virDomainDefParseXML(xmlDocPtr xml,
|
virDomainDefParseXML(xmlDocPtr xml,
|
||||||
xmlNodePtr root,
|
xmlNodePtr root,
|
||||||
@ -19897,6 +20020,18 @@ virDomainDefParseXML(xmlDocPtr xml,
|
|||||||
}
|
}
|
||||||
VIR_FREE(nodes);
|
VIR_FREE(nodes);
|
||||||
|
|
||||||
|
if ((n = virXPathNodeSet("./cputune/memorytune", ctxt, &nodes)) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("cannot extract memorytune nodes"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (virDomainMemorytuneDefParse(def, ctxt, nodes[i], flags) < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
VIR_FREE(nodes);
|
||||||
|
|
||||||
if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu) < 0)
|
if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -27198,6 +27333,68 @@ virDomainCachetuneDefFormat(virBufferPtr buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainMemorytuneDefFormatHelper(unsigned int id,
|
||||||
|
unsigned int bandwidth,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virBufferPtr buf = opaque;
|
||||||
|
|
||||||
|
virBufferAsprintf(buf,
|
||||||
|
"<node id='%u' bandwidth='%u'/>\n",
|
||||||
|
id, bandwidth);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainMemorytuneDefFormat(virBufferPtr buf,
|
||||||
|
virDomainResctrlDefPtr resctrl,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virBuffer childrenBuf = VIR_BUFFER_INITIALIZER;
|
||||||
|
char *vcpus = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
virBufferSetChildIndent(&childrenBuf, buf);
|
||||||
|
if (virResctrlAllocForeachMemory(resctrl->alloc,
|
||||||
|
virDomainMemorytuneDefFormatHelper,
|
||||||
|
&childrenBuf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virBufferCheckError(&childrenBuf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virBufferUse(&childrenBuf)) {
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
vcpus = virBitmapFormat(resctrl->vcpus);
|
||||||
|
if (!vcpus)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
virBufferAsprintf(buf, "<memorytune vcpus='%s'", vcpus);
|
||||||
|
|
||||||
|
if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
|
||||||
|
const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
|
||||||
|
if (!alloc_id)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
virBufferAsprintf(buf, " id='%s'", alloc_id);
|
||||||
|
}
|
||||||
|
virBufferAddLit(buf, ">\n");
|
||||||
|
|
||||||
|
virBufferAddBuffer(buf, &childrenBuf);
|
||||||
|
virBufferAddLit(buf, "</memorytune>\n");
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
virBufferFreeAndReset(&childrenBuf);
|
||||||
|
VIR_FREE(vcpus);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainCputuneDefFormat(virBufferPtr buf,
|
virDomainCputuneDefFormat(virBufferPtr buf,
|
||||||
virDomainDefPtr def,
|
virDomainDefPtr def,
|
||||||
@ -27303,6 +27500,9 @@ virDomainCputuneDefFormat(virBufferPtr buf,
|
|||||||
for (i = 0; i < def->nresctrls; i++)
|
for (i = 0; i < def->nresctrls; i++)
|
||||||
virDomainCachetuneDefFormat(&childrenBuf, def->resctrls[i], flags);
|
virDomainCachetuneDefFormat(&childrenBuf, def->resctrls[i], flags);
|
||||||
|
|
||||||
|
for (i = 0; i < def->nresctrls; i++)
|
||||||
|
virDomainMemorytuneDefFormat(&childrenBuf, def->resctrls[i], flags);
|
||||||
|
|
||||||
if (virBufferCheckError(&childrenBuf) < 0)
|
if (virBufferCheckError(&childrenBuf) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
30
tests/genericxml2xmlindata/memorytune-colliding-allocs.xml
Normal file
30
tests/genericxml2xmlindata/memorytune-colliding-allocs.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory unit='KiB'>219136</memory>
|
||||||
|
<currentMemory unit='KiB'>219136</currentMemory>
|
||||||
|
<vcpu placement='static'>4</vcpu>
|
||||||
|
<cputune>
|
||||||
|
<memorytune vcpus='0'>
|
||||||
|
<node id='0' bandwidth='50'/>
|
||||||
|
<node id='0' bandwidth='50'/>
|
||||||
|
</memorytune>
|
||||||
|
</cputune>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc'>hvm</type>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<clock offset='utc'/>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/usr/bin/qemu-system-i686</emulator>
|
||||||
|
<controller type='usb' index='0'/>
|
||||||
|
<controller type='ide' index='0'/>
|
||||||
|
<controller type='pci' index='0' model='pci-root'/>
|
||||||
|
<input type='mouse' bus='ps2'/>
|
||||||
|
<input type='keyboard' bus='ps2'/>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -0,0 +1,32 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory unit='KiB'>219136</memory>
|
||||||
|
<currentMemory unit='KiB'>219136</currentMemory>
|
||||||
|
<vcpu placement='static'>4</vcpu>
|
||||||
|
<cputune>
|
||||||
|
<cachetune vcpus='0-1'>
|
||||||
|
<cache id='0' level='3' type='code' size='12' unit='KiB'/>
|
||||||
|
</cachetune>
|
||||||
|
<memorytune vcpus='0'>
|
||||||
|
<node id='0' bandwidth='50'/>
|
||||||
|
</memorytune>
|
||||||
|
</cputune>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc'>hvm</type>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<clock offset='utc'/>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/usr/bin/qemu-system-i686</emulator>
|
||||||
|
<controller type='usb' index='0'/>
|
||||||
|
<controller type='ide' index='0'/>
|
||||||
|
<controller type='pci' index='0' model='pci-root'/>
|
||||||
|
<input type='mouse' bus='ps2'/>
|
||||||
|
<input type='keyboard' bus='ps2'/>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
33
tests/genericxml2xmlindata/memorytune.xml
Normal file
33
tests/genericxml2xmlindata/memorytune.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory unit='KiB'>219136</memory>
|
||||||
|
<currentMemory unit='KiB'>219136</currentMemory>
|
||||||
|
<vcpu placement='static'>4</vcpu>
|
||||||
|
<cputune>
|
||||||
|
<memorytune vcpus='0-1'>
|
||||||
|
<node id='0' bandwidth='20'/>
|
||||||
|
<node id='1' bandwidth='30'/>
|
||||||
|
</memorytune>
|
||||||
|
<memorytune vcpus='3'>
|
||||||
|
<node id='0' bandwidth='50'/>
|
||||||
|
</memorytune>
|
||||||
|
</cputune>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc'>hvm</type>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<clock offset='utc'/>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/usr/bin/qemu-system-i686</emulator>
|
||||||
|
<controller type='usb' index='0'/>
|
||||||
|
<controller type='ide' index='0'/>
|
||||||
|
<controller type='pci' index='0' model='pci-root'/>
|
||||||
|
<input type='mouse' bus='ps2'/>
|
||||||
|
<input type='keyboard' bus='ps2'/>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -140,6 +140,11 @@ mymain(void)
|
|||||||
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
|
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
|
||||||
DO_TEST_FULL("cachetune-colliding-types", false, true,
|
DO_TEST_FULL("cachetune-colliding-types", false, true,
|
||||||
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
|
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
|
||||||
|
DO_TEST("memorytune");
|
||||||
|
DO_TEST_FULL("memorytune-colliding-allocs", false, true,
|
||||||
|
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
|
||||||
|
DO_TEST_FULL("memorytune-colliding-cachetune", false, true,
|
||||||
|
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
|
||||||
|
|
||||||
DO_TEST("tseg");
|
DO_TEST("tseg");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user