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:
Bing Niu 2018-07-30 11:12:39 +08:00 committed by John Ferlan
parent 72824f67cd
commit 6956b7eedc
7 changed files with 355 additions and 1 deletions

View File

@ -759,6 +759,10 @@
&lt;cache id='0' level='3' type='both' size='3' unit='MiB'/&gt;
&lt;cache id='1' level='3' type='both' size='3' unit='MiB'/&gt;
&lt;/cachetune&gt;
&lt;memorytune vcpus='0-3'&gt;
&lt;node id='0' bandwidth='60'/&gt;
&lt;/memorytune&gt;
&lt;/cputune&gt;
...
&lt;/domain&gt;
@ -932,7 +936,9 @@
size 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>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>
<dt><code>cache</code></dt>
<dd>
@ -972,7 +978,38 @@
</dl>
</dd>
</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>
</dl>

View File

@ -983,6 +983,23 @@
</oneOrMore>
</element>
</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>
</element>
</define>

View File

@ -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
virDomainDefParseXML(xmlDocPtr xml,
xmlNodePtr root,
@ -19897,6 +20020,18 @@ virDomainDefParseXML(xmlDocPtr xml,
}
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)
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
virDomainCputuneDefFormat(virBufferPtr buf,
virDomainDefPtr def,
@ -27303,6 +27500,9 @@ virDomainCputuneDefFormat(virBufferPtr buf,
for (i = 0; i < def->nresctrls; i++)
virDomainCachetuneDefFormat(&childrenBuf, def->resctrls[i], flags);
for (i = 0; i < def->nresctrls; i++)
virDomainMemorytuneDefFormat(&childrenBuf, def->resctrls[i], flags);
if (virBufferCheckError(&childrenBuf) < 0)
return -1;

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

View File

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

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

View File

@ -140,6 +140,11 @@ mymain(void)
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
DO_TEST_FULL("cachetune-colliding-types", false, true,
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");