[libvirt] [PATCH v2 08/16] conf, schema: add support for memnode elements

Michal Privoznik mprivozn at redhat.com
Fri Jul 11 15:10:53 UTC 2014


On 08.07.2014 13:50, Martin Kletzander wrote:
> Signed-off-by: Martin Kletzander <mkletzan at 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




More information about the libvir-list mailing list