On 08.07.2014 13:50, Martin Kletzander wrote:
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
docs/formatdomain.html.in | 15 ++
docs/schemas/domaincommon.rng | 17 ++
src/conf/numatune_conf.c | 183 +++++++++++++++++++--
.../qemuxml2argv-numatune-memnode-no-memory.xml | 30 ++++
.../qemuxml2argv-numatune-memnode-nocpu.xml | 25 +++
.../qemuxml2argv-numatune-memnode.xml | 31 ++++
.../qemuxml2argv-numatune-memnodes-problematic.xml | 31 ++++
tests/qemuxml2argvtest.c | 2 +
.../qemuxml2xmlout-numatune-memnode.xml | 33 ++++
tests/qemuxml2xmltest.c | 2 +
10 files changed, 356 insertions(+), 13 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-memnode-no-memory.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-memnode-nocpu.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-memnode.xml
create mode 100644
tests/qemuxml2argvdata/qemuxml2argv-numatune-memnodes-problematic.xml
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index ad87b7c..d845c1b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -709,6 +709,8 @@
...
<numatune>
<memory mode="strict" nodeset="1-4,^3"/>
+ <memnode cellid="0" mode="strict"
nodeset="1"/>
+ <memnode cellid="2" mode="preferred"
nodeset="2"/>
</numatune>
...
</domain>
@@ -745,6 +747,19 @@
<span class='since'>Since 0.9.3</span>
</dd>
+ <dt><code>memnode</code></dt>
+ <dd>
+ Optional <code>memnode</code> elements can specify memory
allocation
+ policies per each guest NUMA node. For those nodes having no
+ corresponding <code>memnode</code> element, the default from
+ element <code>memory</code> will be used. Attribute
<code>cellid</code>
+ addresses guest NUMA node for which the settings are applied.
+ Attributes <code>mode</code> and <code>nodeset</code>
have the same
+ meaning and syntax as in <code>memory</code> element.
+
+ This setting is not compatible with automatic placement.
+ <span class='since'>QEMU Since 1.2.6</span>
1.2.8 actually
+ </dd>
</dl>
+static int
+virDomainNumatuneNodeParseXML(virDomainDefPtr def,
+ xmlXPathContextPtr ctxt)
+{
+ int n = 0;;
+ int ret = -1;
+ size_t i = 0;
+ xmlNodePtr *nodes = NULL;
+
+ if ((n = virXPathNodeSet("./numatune/memnode", ctxt, &nodes)) < 0)
{
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot extract memnode nodes"));
+ goto cleanup;
+ }
+
+ if (!n)
+ return 0;
+
+ if (def->numatune && def->numatune->memory.specified &&
+ def->numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Per-node binding is not compatible with "
+ "automatic NUMA placement."));
+ goto cleanup;
+ }
+
+ if (!def->cpu || !def->cpu->ncells) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Element 'memnode' is invalid without "
+ "any guest NUMA cells"));
+ goto cleanup;
+ }
+
+ if (!def->numatune && VIR_ALLOC(def->numatune) < 0)
+ goto cleanup;
Here you allow def->numatune to be allocated already.
+
+ if (VIR_ALLOC_N(def->numatune->mem_nodes, def->cpu->ncells) < 0)
+ goto cleanup;
Which means, this can exists too. VIR_REALLOC_N() is safer IMO.
+
+ def->numatune->nmem_nodes = def->cpu->ncells;
+
+ for (i = 0; i < n; i++) {
+ const char *tmp = NULL;
No. s/const//.
+ int mode = 0;
+ unsigned int cellid = 0;
+ virDomainNumatuneNodePtr mem_node = NULL;
+ xmlNodePtr cur_node = nodes[i];
+
+ tmp = virXMLPropString(cur_node, "cellid");
+ if (!tmp) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Missing required cellid attribute "
+ "in memnode element"));
+ goto cleanup;
+ }
+ if (virStrToLong_uip(tmp, NULL, 10, &cellid) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid cellid attribute in memnode element"));
Moreover, @tmp is leaked here. And it would be nice to tell users in the error message
@tmp somehow.
+ goto cleanup;
+ }
+ VIR_FREE(tmp);
+
+ if (cellid >= def->numatune->nmem_nodes) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Argument 'cellid' in memnode element must
"
+ "correspond to existing guest's NUMA
cell"));
+ goto cleanup;
+ }
+
+ mem_node = &def->numatune->mem_nodes[cellid];
+
+ if (mem_node->nodeset) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Multiple memnode elements with cellid %u"),
+ cellid);
+ goto cleanup;
+ }
+
+ tmp = virXMLPropString(cur_node, "mode");
+ if (!tmp) {
+ mem_node->mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+ } else {
+ if ((mode = virDomainNumatuneMemModeTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid mode attribute in memnode
element"));
+ goto cleanup;
+ }
+ VIR_FREE(tmp);
+ mem_node->mode = mode;
+ }
+
+ tmp = virXMLPropString(cur_node, "nodeset");
+ if (!tmp) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Missing required nodeset attribute "
+ "in memnode element"));
+ goto cleanup;
+ }
+ if (virBitmapParse(tmp, 0, &mem_node->nodeset,
+ VIR_DOMAIN_CPUMASK_LEN) < 0)
+ goto cleanup;
+ VIR_FREE(tmp);
+ }
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(nodes);
+ return ret;
+}
+
diff --git
a/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
new file mode 100644
index 0000000..82b5f61
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
Are you sure this is the correct content?
@@ -0,0 +1,33 @@
+<domain type='qemu'>
+ <name>QEMUGuest</name>
+ <uuid>9f4b6512-e73a-4a25-93e8-5307802821ce</uuid>
+ <memory unit='KiB'>24682468</memory>
In the qemuxml2argvdata/qemuxml2argv-numatune-memnode.xml you have 65MB of RAM while here
~23.5GB.
+ <currentMemory
unit='KiB'>24682468</currentMemory>
+ <vcpu placement='static'>32</vcpu>
and only 2 vcpus, while here is 32.
+ <numatune>
+ <memory mode='strict' nodeset='0-7'/>
+ <memnode cellid='0' mode='preferred' nodeset='3'/>
+ <memnode cellid='2' mode='strict' nodeset='1-2,5,7'/>
+ </numatune>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <cpu>
+ <numa>
+ <cell id='0' cpus='0' memory='20002'/>
+ <cell id='1' cpus='1-27,29' memory='660066'/>
+ <cell id='2' cpus='28-31,^29' memory='24002400'/>
And this is broken too.
+ </numa>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/kvm</emulator>
+ <controller type='usb' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 3bba565..4beb799 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -372,6 +372,8 @@ mymain(void)
DO_TEST_DIFFERENT("cpu-numa2");
DO_TEST_DIFFERENT("numatune-auto-prefer");
+ DO_TEST_DIFFERENT("numatune-memnode");
+ DO_TEST("numatune-memnode-no-memory");
virObjectUnref(driver.caps);
virObjectUnref(driver.xmlopt);
I can't ACK this one, until the issue is resolved. If I squash this in, the test
passes again:
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
index 82b5f61..18b00d8 100644
--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-memnode.xml
@@ -1,13 +1,12 @@
<domain type='qemu'>
<name>QEMUGuest</name>
<uuid>9f4b6512-e73a-4a25-93e8-5307802821ce</uuid>
- <memory unit='KiB'>24682468</memory>
- <currentMemory unit='KiB'>24682468</currentMemory>
- <vcpu placement='static'>32</vcpu>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>65536</currentMemory>
+ <vcpu placement='static'>2</vcpu>
<numatune>
- <memory mode='strict' nodeset='0-7'/>
+ <memory mode='strict' nodeset='0-3'/>
<memnode cellid='0' mode='preferred' nodeset='3'/>
- <memnode cellid='2' mode='strict' nodeset='1-2,5,7'/>
</numatune>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
@@ -15,9 +14,8 @@
</os>
<cpu>
<numa>
- <cell id='0' cpus='0' memory='20002'/>
- <cell id='1' cpus='1-27,29' memory='660066'/>
- <cell id='2' cpus='28-31,^29' memory='24002400'/>
+ <cell id='0' cpus='0' memory='32768'/>
+ <cell id='1' cpus='1' memory='32768'/>
</numa>
</cpu>
<clock offset='utc'/>
Michal