[PATCH LIBVIRT v1 2/2] xen: Handle maxcpus in xl configutation files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This new cfg field was addded in 4.0 by 68a94cf528e6 "xm: Add maxvcpus
support" and, more crucially these day, it is what xl supports.

This removes the MAX_VIRT_CPUS limitation for such versions of Xen
(since maxvcpus is simply a count, not a bit mask) which is
particularly crucial on ARM where MAX_VIRT_CPUS == 1 (since all guests
are expected to support vcpu placement, and therefore only the boot
vcpu's info lives in the shared info page).

Add a new test case to both XM and XL config tests covering this case.

Note that although xm gained support for maxvcpus in Xen 4.0 the
xend_config_format was never bumped beyond 4 and the internal handling
remained in terms of vcpu_avail. Therefore the support for
xend >= XEND_CONFIG_VERSION_4_0_0 is somewhat theoretical.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 src/xenconfig/xen_common.c                    | 72 ++++++++++++++++++++-------
 src/xenconfig/xen_xm.c                        |  7 +++
 tests/xlconfigdata/test-paravirt-maxvcpus.cfg | 13 +++++
 tests/xlconfigdata/test-paravirt-maxvcpus.xml | 28 +++++++++++
 tests/xlconfigtest.c                          |  1 +
 tests/xmconfigdata/test-paravirt-maxvcpus.cfg | 13 +++++
 tests/xmconfigdata/test-paravirt-maxvcpus.xml | 30 +++++++++++
 tests/xmconfigtest.c                          |  1 +
 8 files changed, 146 insertions(+), 19 deletions(-)
 create mode 100644 tests/xlconfigdata/test-paravirt-maxvcpus.cfg
 create mode 100644 tests/xlconfigdata/test-paravirt-maxvcpus.xml
 create mode 100644 tests/xmconfigdata/test-paravirt-maxvcpus.cfg
 create mode 100644 tests/xmconfigdata/test-paravirt-maxvcpus.xml

diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c
index 0890c73..6f2afcc 100644
--- a/src/xenconfig/xen_common.c
+++ b/src/xenconfig/xen_common.c
@@ -492,24 +492,49 @@ xenParsePCI(virConfPtr conf, virDomainDefPtr def)
 
 
 static int
-xenParseCPUFeatures(virConfPtr conf, virDomainDefPtr def)
+xenParseCPUFeatures(virConfPtr conf, virDomainDefPtr def,
+                    int xendConfigVersion)
 {
     unsigned long count = 0;
     const char *str = NULL;
     int val = 0;
 
-    if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
-        MAX_VIRT_CPUS < count)
-        return -1;
+    /*
+     * xend prior to 4.0 understands vcpus as maxvcpus and vcpu_avail
+     * as a bit map of which cpus are online (default is all).
+     *
+     * xend from 4.0 onwards understands maxvcpus as maxvcpus and
+     * vcpus as the number which are online (from 0..N-1). The
+     * upstream commit (68a94cf528e6 "xm: Add maxvcpus support")
+     * claims that if maxvcpus is omitted then the old behaviour
+     * (i.e. obeying vcpu_avail) is retained, but AFAICT it was not,
+     * in this case vcpu==maxcpus==online cpus. This is good for us
+     * because handling anything else would be fiddly.
+     *
+     * xl understands vcpus + maxvcpus, but not vcpu_avail
+     * (ever).
+     */
+    if (xendConfigVersion < XEND_CONFIG_VERSION_4_0_0) {
+        if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
+            MAX_VIRT_CPUS < count)
+            return -1;
+        def->maxvcpus = count;
 
-    def->maxvcpus = count;
-    if (xenConfigGetULong(conf, "vcpu_avail", &count, -1) < 0)
-        return -1;
+        if (xenConfigGetULong(conf, "vcpu_avail", &count, -1) < 0)
+            return -1;
+        def->vcpus = MIN(count_one_bits_l(count), def->maxvcpus);
+    } else {
+        if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0)
+            return -1;
+        def->vcpus = count;
+
+        if (xenConfigGetULong(conf, "maxvcpus", &count, def->vcpus) < 0)
+            return -1;
+        def->maxvcpus = count;
+    }
 
-    def->vcpus = MIN(count_one_bits_l(count), def->maxvcpus);
     if (xenConfigGetString(conf, "cpus", &str, NULL) < 0)
         return -1;
-
     if (str && (virBitmapParse(str, 0, &def->cpumask, 4096) < 0))
         return -1;
 
@@ -1032,7 +1057,7 @@ xenParseConfigCommon(virConfPtr conf,
     if (xenParseEventsActions(conf, def) < 0)
         return -1;
 
-    if (xenParseCPUFeatures(conf, def) < 0)
+    if (xenParseCPUFeatures(conf, def, xendConfigVersion) < 0)
         return -1;
 
     if (xenParseTimeOffset(conf, def, xendConfigVersion) < 0)
@@ -1519,19 +1544,28 @@ xenFormatCharDev(virConfPtr conf, virDomainDefPtr def)
 
 
 static int
-xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def)
+xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def,
+                       int xendConfigVersion)
 {
     int ret = -1;
     char *cpus = NULL;
 
-    if (xenConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
-        goto cleanup;
+    if (xendConfigVersion >= XEND_CONFIG_VERSION_4_0_0) {
+        if (def->vcpus < def->maxvcpus &&
+            xenConfigSetInt(conf, "maxvcpus", def->maxvcpus) < 0)
+            goto cleanup;
+        if (xenConfigSetInt(conf, "vcpus", def->vcpus) < 0)
+            goto cleanup;
+    } else {
+        if (xenConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
+            goto cleanup;
 
-    /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
-       either 32, or 64 on a platform where long is big enough.  */
-    if (def->vcpus < def->maxvcpus &&
-        xenConfigSetInt(conf, "vcpu_avail", (1UL << def->vcpus) - 1) < 0)
-        goto cleanup;
+        /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
+           either 32, or 64 on a platform where long is big enough.  */
+        if (def->vcpus < def->maxvcpus &&
+            xenConfigSetInt(conf, "vcpu_avail", (1UL << def->vcpus) - 1) < 0)
+            goto cleanup;
+    }
 
     if ((def->cpumask != NULL) &&
         ((cpus = virBitmapFormat(def->cpumask)) == NULL)) {
@@ -1826,7 +1860,7 @@ xenFormatConfigCommon(virConfPtr conf,
     if (xenFormatMem(conf, def) < 0)
         return -1;
 
-    if (xenFormatCPUAllocation(conf, def) < 0)
+    if (xenFormatCPUAllocation(conf, def, xendConfigVersion) < 0)
         return -1;
 
     if (xenFormatCPUFeatures(conf, def, xendConfigVersion) < 0)
diff --git a/src/xenconfig/xen_xm.c b/src/xenconfig/xen_xm.c
index a4d1203..a2981f7 100644
--- a/src/xenconfig/xen_xm.c
+++ b/src/xenconfig/xen_xm.c
@@ -482,6 +482,13 @@ xenParseXM(virConfPtr conf,
     if (xenParseConfigCommon(conf, def, caps, xendConfigVersion) < 0)
         goto cleanup;
 
+    /*
+     * xend vcpu_avail field is an integer bitmap, so cannot handle more than
+     * MAX_VIRT_CPUS.
+     */
+    if (MAX_VIRT_CPUS < def->maxvcpus || MAX_VIRT_CPUS < def->vcpus)
+        goto cleanup;
+
     if (xenParseXMOS(conf, def) < 0)
          goto cleanup;
 
diff --git a/tests/xlconfigdata/test-paravirt-maxvcpus.cfg b/tests/xlconfigdata/test-paravirt-maxvcpus.cfg
new file mode 100644
index 0000000..d506b75
--- /dev/null
+++ b/tests/xlconfigdata/test-paravirt-maxvcpus.cfg
@@ -0,0 +1,13 @@
+name = "XenGuest1"
+uuid = "45b60f51-88a9-47a8-a3b3-5e66d71b2283"
+maxmem = 512
+memory = 512
+maxvcpus = 8
+vcpus = 4
+localtime = 0
+on_poweroff = "preserve"
+on_reboot = "restart"
+on_crash = "preserve"
+vif = [ "mac=5a:36:0e:be:00:09" ]
+bootloader = "/usr/bin/pygrub"
+disk = [ "/var/lib/xen/images/debian/disk.qcow2,qcow2,xvda,w,backendtype=qdisk" ]
diff --git a/tests/xlconfigdata/test-paravirt-maxvcpus.xml b/tests/xlconfigdata/test-paravirt-maxvcpus.xml
new file mode 100644
index 0000000..2e1f8f8
--- /dev/null
+++ b/tests/xlconfigdata/test-paravirt-maxvcpus.xml
@@ -0,0 +1,28 @@
+<domain type='xen'>
+  <name>XenGuest1</name>
+  <uuid>45b60f51-88a9-47a8-a3b3-5e66d71b2283</uuid>
+  <memory unit='KiB'>524288</memory>
+  <currentMemory unit='KiB'>524288</currentMemory>
+  <vcpu placement='static' current='4'>8</vcpu>
+  <bootloader>/usr/bin/pygrub</bootloader>
+  <os>
+    <type arch='x86_64' machine='xenpv'>linux</type>
+  </os>
+  <clock offset='utc' adjustment='reset'/>
+  <on_poweroff>preserve</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>preserve</on_crash>
+  <devices>
+    <disk type='file' device='disk'>
+      <driver name='qemu' type='qcow2'/>
+      <source file='/var/lib/xen/images/debian/disk.qcow2'/>
+      <target dev='xvda' bus='xen'/>
+    </disk>
+    <interface type='ethernet'>
+      <mac address='5a:36:0e:be:00:09'/>
+    </interface>
+    <console type='pty'>
+      <target type='xen' port='0'/>
+    </console>
+  </devices>
+</domain>
diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c
index 08c43fb..b6f9b84 100644
--- a/tests/xlconfigtest.c
+++ b/tests/xlconfigtest.c
@@ -193,6 +193,7 @@ mymain(void)
             ret = -1;                                                   \
     } while (0)
 
+    DO_TEST("paravirt-maxvcpus", 5);
     DO_TEST("new-disk", 5);
     DO_TEST("spice", 5);
     DO_TEST("spice-features", 5);
diff --git a/tests/xmconfigdata/test-paravirt-maxvcpus.cfg b/tests/xmconfigdata/test-paravirt-maxvcpus.cfg
new file mode 100644
index 0000000..8d1ac4d
--- /dev/null
+++ b/tests/xmconfigdata/test-paravirt-maxvcpus.cfg
@@ -0,0 +1,13 @@
+name = "XenGuest1"
+uuid = "c7a5fdb0-cdaf-9455-926a-d65c16db1809"
+maxmem = 579
+memory = 394
+maxvcpus = 4
+vcpus = 2
+localtime = 0
+on_poweroff = "destroy"
+on_reboot = "restart"
+on_crash = "restart"
+vif = [ "mac=00:16:3e:66:94:9c,bridge=br0,script=vif-bridge" ]
+bootloader = "/usr/bin/pygrub"
+disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ]
diff --git a/tests/xmconfigdata/test-paravirt-maxvcpus.xml b/tests/xmconfigdata/test-paravirt-maxvcpus.xml
new file mode 100644
index 0000000..52463d8
--- /dev/null
+++ b/tests/xmconfigdata/test-paravirt-maxvcpus.xml
@@ -0,0 +1,30 @@
+<domain type='xen'>
+  <name>XenGuest1</name>
+  <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>592896</memory>
+  <currentMemory unit='KiB'>403456</currentMemory>
+  <vcpu placement='static' current='2'>4</vcpu>
+  <bootloader>/usr/bin/pygrub</bootloader>
+  <os>
+    <type arch='i686' machine='xenpv'>linux</type>
+  </os>
+  <clock offset='utc' adjustment='reset'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <disk type='block' device='disk'>
+      <driver name='phy'/>
+      <source dev='/dev/HostVG/XenGuest1'/>
+      <target dev='xvda' bus='xen'/>
+    </disk>
+    <interface type='bridge'>
+      <mac address='00:16:3e:66:94:9c'/>
+      <source bridge='br0'/>
+      <script path='vif-bridge'/>
+    </interface>
+    <console type='pty'>
+      <target type='xen' port='0'/>
+    </console>
+  </devices>
+</domain>
diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c
index 79b09ca..ff1f52b 100644
--- a/tests/xmconfigtest.c
+++ b/tests/xmconfigtest.c
@@ -220,6 +220,7 @@ mymain(void)
     DO_TEST("paravirt-net-e1000", 3);
     DO_TEST("paravirt-net-vifname", 3);
     DO_TEST("paravirt-vcpu", 2);
+    DO_TEST("paravirt-maxvcpus", 5);
     DO_TEST("fullvirt-old-cdrom", 1);
     DO_TEST("fullvirt-new-cdrom", 2);
     DO_TEST("fullvirt-utc", 2);
-- 
2.1.4

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]