提交 6956b7ee 编写于 作者: B Bing Niu 提交者: John Ferlan

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: NBing Niu <bing.niu@intel.com>
Reviewed-by: NJohn Ferlan <jferlan@redhat.com>
上级 72824f67
......@@ -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>
......
......@@ -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>
......
......@@ -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;
......
<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>
<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>
<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);
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");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册