[libvirt] [PATCH 1/6] conf, schema: add 'id' field for cells

Martin Kletzander mkletzan at redhat.com
Wed Jun 4 14:56:27 UTC 2014


In XML format, by definition, order of fields should not matter, so
oder of parsing the elements doesn't affect the end result.  When
specifying guest NUMA cells, we depend only on the order of the 'cell'
elements.  With this patch all older domain XMLs are parsed as before,
but with the 'id' attribute they are parsed and formatted according to
that field.  This will be useful when we have tuning settings for
particular guest NUMA node.

Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
---
 docs/formatdomain.html.in                          | 11 +++---
 docs/schemas/domaincommon.rng                      |  5 +++
 src/conf/cpu_conf.c                                | 39 +++++++++++++++++++---
 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa1.xml  |  6 ++--
 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa2.xml  |  6 ++--
 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml  | 25 ++++++++++++++
 tests/qemuxml2argvtest.c                           |  1 +
 .../qemuxml2xmlout-cpu-numa1.xml                   | 28 ++++++++++++++++
 .../qemuxml2xmlout-cpu-numa2.xml                   | 28 ++++++++++++++++
 tests/qemuxml2xmltest.c                            |  3 ++
 10 files changed, 138 insertions(+), 14 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml
 create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa1.xml
 create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa2.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 691a451..041f70d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1030,8 +1030,8 @@
   <cpu>
     ...
     <numa>
-      <cell cpus='0-3' memory='512000'/>
-      <cell cpus='4-7' memory='512000'/>
+      <cell id='0' cpus='0-3' memory='512000'/>
+      <cell id='1' cpus='4-7' memory='512000'/>
     </numa>
     ...
   </cpu>
@@ -1041,8 +1041,11 @@
       Each <code>cell</code> element specifies a NUMA cell or a NUMA node.
       <code>cpus</code> specifies the CPU or range of CPUs that are part of
       the node. <code>memory</code> specifies the node memory in kibibytes
-      (i.e. blocks of 1024 bytes). Each cell or node is assigned cellid
-      or nodeid in the increasing order starting from 0.
+      (i.e. blocks of 1024 bytes). All cells should have <code>id</code>
+      attribute in case referring to some cell is necessary in the code,
+      otherwise the cells are assigned ids in the increasing order starting
+      from 0.  Mixing cells with and without the <code>id</code> attribute
+      is not recommended as it may result in unwanted behaviour.
     </p>

     <p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index af67123..0787b5a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3892,6 +3892,11 @@

   <define name="numaCell">
     <element name="cell">
+      <optional>
+        <attribute name="id">
+          <ref name="unsignedInt"/>
+        </attribute>
+      </optional>
       <attribute name="cpus">
         <ref name="cpuset"/>
       </attribute>
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
index ebdaa19..ec80340 100644
--- a/src/conf/cpu_conf.c
+++ b/src/conf/cpu_conf.c
@@ -438,17 +438,47 @@ virCPUDefParseXML(xmlNodePtr node,
         for (i = 0; i < n; i++) {
             char *cpus, *memory;
             int ret, ncpus = 0;
+            unsigned int cur_cell;
+            char *tmp = NULL;
+
+            tmp = virXMLPropString(nodes[i], "id");
+            if (!tmp) {
+                cur_cell = i;
+            } else {
+                ret  = virStrToLong_ui(tmp, NULL, 10, &cur_cell);
+                VIR_FREE(tmp);
+                if (ret == -1) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("Invalid 'id' attribute in NUMA cell"));
+                    goto error;
+                }
+            }
+
+            if (cur_cell >= n) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("Exactly one 'cell' element per guest "
+                                 "NUMA cell allowed, non-contiguous ranges or "
+                                 "ranges not starting from 0 are not allowed"));
+                goto error;
+            }
+
+            if (def->cells[cur_cell].cpustr) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("Duplicate NUMA cell info for cell id '%u'"),
+                               cur_cell);
+                goto error;
+            }

-            def->cells[i].cellid = i;
+            def->cells[cur_cell].cellid = cur_cell;
             cpus = virXMLPropString(nodes[i], "cpus");
             if (!cpus) {
                 virReportError(VIR_ERR_XML_ERROR, "%s",
                                _("Missing 'cpus' attribute in NUMA cell"));
                 goto error;
             }
-            def->cells[i].cpustr = cpus;
+            def->cells[cur_cell].cpustr = cpus;

-            ncpus = virBitmapParse(cpus, 0, &def->cells[i].cpumask,
+            ncpus = virBitmapParse(cpus, 0, &def->cells[cur_cell].cpumask,
                                    VIR_DOMAIN_CPUMASK_LEN);
             if (ncpus <= 0)
                 goto error;
@@ -461,7 +491,7 @@ virCPUDefParseXML(xmlNodePtr node,
                 goto error;
             }

-            ret  = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
+            ret  = virStrToLong_ui(memory, NULL, 10, &def->cells[cur_cell].mem);
             if (ret == -1) {
                 virReportError(VIR_ERR_XML_ERROR, "%s",
                                _("Invalid 'memory' attribute in NUMA cell"));
@@ -647,6 +677,7 @@ virCPUDefFormatBuf(virBufferPtr buf,
         virBufferAdjustIndent(buf, 2);
         for (i = 0; i < def->ncells; i++) {
             virBufferAddLit(buf, "<cell");
+            virBufferAsprintf(buf, " id='%u'", def->cells[i].cellid);
             virBufferAsprintf(buf, " cpus='%s'", def->cells[i].cpustr);
             virBufferAsprintf(buf, " memory='%d'", def->cells[i].mem);
             virBufferAddLit(buf, "/>\n");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa1.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa1.xml
index ee402c8..0543f7f 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa1.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa1.xml
@@ -9,10 +9,10 @@
     <boot dev='network'/>
   </os>
   <cpu>
-    <topology sockets="2" cores="4" threads="2"/>
+    <topology sockets='2' cores='4' threads='2'/>
     <numa>
-      <cell cpus="0-7" memory="109550"/>
-      <cell cpus="8-15" memory="109550"/>
+      <cell cpus='0-7' memory='109550'/>
+      <cell cpus='8-15' memory='109550'/>
     </numa>
   </cpu>
   <clock offset='utc'/>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa2.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa2.xml
index ee402c8..0a5f9fc 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa2.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa2.xml
@@ -9,10 +9,10 @@
     <boot dev='network'/>
   </os>
   <cpu>
-    <topology sockets="2" cores="4" threads="2"/>
+    <topology sockets='2' cores='4' threads='2'/>
     <numa>
-      <cell cpus="0-7" memory="109550"/>
-      <cell cpus="8-15" memory="109550"/>
+      <cell id='1' cpus='8-15' memory='109550'/>
+      <cell id='0' cpus='0-7' memory='109550'/>
     </numa>
   </cpu>
   <clock offset='utc'/>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml
new file mode 100644
index 0000000..fa3070d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml
@@ -0,0 +1,25 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>16</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='network'/>
+  </os>
+  <cpu>
+    <topology sockets='2' cores='4' threads='2'/>
+    <numa>
+      <cell id='1' cpus='0-7' memory='109550'/>
+      <cell id='2' cpus='8-15' memory='109550'/>
+    </numa>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+      <emulator>/usr/bin/qemu</emulator>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 24d104e..bdea8b0 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1169,6 +1169,7 @@ mymain(void)
     DO_TEST("cpu-strict1", NONE);
     DO_TEST("cpu-numa1", NONE);
     DO_TEST("cpu-numa2", QEMU_CAPS_SMP_TOPOLOGY);
+    DO_TEST_PARSE_ERROR("cpu-numa3", NONE);
     DO_TEST("cpu-host-model", NONE);
     skipLegacyCPUs = true;
     DO_TEST("cpu-host-model-fallback", NONE);
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa1.xml
new file mode 100644
index 0000000..227bf1c
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa1.xml
@@ -0,0 +1,28 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>16</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='network'/>
+  </os>
+  <cpu>
+    <topology sockets='2' cores='4' threads='2'/>
+    <numa>
+      <cell id='0' cpus='0-7' memory='109550'/>
+      <cell id='1' cpus='8-15' memory='109550'/>
+    </numa>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa2.xml
new file mode 100644
index 0000000..227bf1c
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa2.xml
@@ -0,0 +1,28 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>16</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='network'/>
+  </os>
+  <cpu>
+    <topology sockets='2' cores='4' threads='2'/>
+    <numa>
+      <cell id='0' cpus='0-7' memory='109550'/>
+      <cell id='1' cpus='8-15' memory='109550'/>
+    </numa>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</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 da528da..a446ea1 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -364,6 +364,9 @@ mymain(void)

     DO_TEST("chardev-label");

+    DO_TEST_DIFFERENT("cpu-numa1");
+    DO_TEST_DIFFERENT("cpu-numa2");
+
     virObjectUnref(driver.caps);
     virObjectUnref(driver.xmlopt);

-- 
2.0.0




More information about the libvir-list mailing list