]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Allow system pages to <memoryBacking/>
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 12 Dec 2014 09:37:35 +0000 (10:37 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 15 Dec 2014 12:36:47 +0000 (13:36 +0100)
https://bugzilla.redhat.com/show_bug.cgi?id=1173507

It occurred to me that OpenStack uses the following XML when not using
regular huge pages:

  <memoryBacking>
    <hugepages>
      <page size='4' unit='KiB'/>
    </hugepages>
  </memoryBacking>

However, since we are expecting to see huge pages only, we fail to
startup the domain with following error:

  libvirtError: internal error: Unable to find any usable hugetlbfs
  mount for 4 KiB

While regular system pages are not huge pages technically, our code is
prepared for that and if it helps OpenStack (or other management
applications) we should cope with that.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_command.c
tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c

index 48bdf4ebe4465abafcd2d5bd78de8e4650d0e48c..c44560f2991c35ede22f557654f48325954734e0 100644 (file)
@@ -6616,6 +6616,7 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
     char *nodemask = NULL;
     char *mem_path = NULL;
     int ret = -1;
+    const long system_page_size = sysconf(_SC_PAGESIZE);
 
     if (virDomainNumatuneHasPerNodeBinding(def->numatune) &&
         !(virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
@@ -6626,7 +6627,8 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
         goto cleanup;
     }
 
-    if (def->mem.nhugepages && def->mem.hugepages[0].size &&
+    if (def->mem.nhugepages &&
+        def->mem.hugepages[0].size != system_page_size &&
         !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("huge pages per NUMA node are not "
@@ -6720,6 +6722,13 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
                 hugepage = master_hugepage;
             }
 
+            if (hugepage && hugepage->size == system_page_size) {
+                /* However, if user specified to use "huge" page
+                 * of regular system page size, it's as if they
+                 * hasn't specified any huge pages at all. */
+                hugepage = NULL;
+            }
+
             if (hugepage) {
                 /* Now lets see, if the huge page we want to use is even mounted
                  * and ready to use */
@@ -7882,44 +7891,51 @@ qemuBuildCommandLine(virConnectPtr conn,
     def->mem.max_balloon = VIR_DIV_UP(def->mem.max_balloon, 1024) * 1024;
     virCommandAddArgFormat(cmd, "%llu", def->mem.max_balloon / 1024);
     if (def->mem.nhugepages && (!def->cpu || !def->cpu->ncells)) {
-        char *mem_path;
+        const long system_page_size = sysconf(_SC_PAGESIZE) / 1024;
+        char *mem_path = NULL;
 
-        if (!cfg->nhugetlbfs) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("hugetlbfs filesystem is not mounted "
-                                   "or disabled by administrator config"));
-            goto error;
-        }
-        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_PATH)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("hugepage backing not supported by '%s'"),
-                           def->emulator);
-            goto error;
-        }
-
-        if (def->mem.hugepages[0].size) {
-            for (j = 0; j < cfg->nhugetlbfs; j++) {
-                if (cfg->hugetlbfs[j].size == def->mem.hugepages[0].size)
-                    break;
+        if (def->mem.hugepages[0].size == system_page_size) {
+            /* There is one special case: if user specified "huge"
+             * pages of regular system pages size. */
+        } else {
+            if (!cfg->nhugetlbfs) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("hugetlbfs filesystem is not mounted "
+                                       "or disabled by administrator config"));
+                goto error;
             }
-
-            if (j == cfg->nhugetlbfs) {
+            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_PATH)) {
                 virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Unable to find any usable hugetlbfs mount for %llu KiB"),
-                               def->mem.hugepages[0].size);
+                               _("hugepage backing not supported by '%s'"),
+                               def->emulator);
                 goto error;
             }
 
-            if (!(mem_path = qemuGetHugepagePath(&cfg->hugetlbfs[j])))
-                goto error;
-        } else {
-            if (!(mem_path = qemuGetDefaultHugepath(cfg->hugetlbfs,
-                                                    cfg->nhugetlbfs)))
-                goto error;
+            if (def->mem.hugepages[0].size) {
+                for (j = 0; j < cfg->nhugetlbfs; j++) {
+                    if (cfg->hugetlbfs[j].size == def->mem.hugepages[0].size)
+                        break;
+                }
+
+                if (j == cfg->nhugetlbfs) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("Unable to find any usable hugetlbfs mount for %llu KiB"),
+                                   def->mem.hugepages[0].size);
+                    goto error;
+                }
+
+                if (!(mem_path = qemuGetHugepagePath(&cfg->hugetlbfs[j])))
+                    goto error;
+            } else {
+                if (!(mem_path = qemuGetDefaultHugepath(cfg->hugetlbfs,
+                                                        cfg->nhugetlbfs)))
+                    goto error;
+            }
         }
 
-        virCommandAddArgList(cmd, "-mem-prealloc", "-mem-path",
-                             mem_path, NULL);
+        virCommandAddArg(cmd, "-mem-prealloc");
+        if (mem_path)
+            virCommandAddArgList(cmd, "-mem-path", mem_path, NULL);
         VIR_FREE(mem_path);
     }
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.args b/tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.args
new file mode 100644 (file)
index 0000000..4eccb86
--- /dev/null
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc -m 1024 -mem-prealloc -smp 2 -nographic \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
+-hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.xml b/tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.xml
new file mode 100644 (file)
index 0000000..4f318fd
--- /dev/null
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>SomeDummyHugepagesGuest</name>
+  <uuid>ef1bdff4-27f3-4e85-a807-5fb4d58463cc</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <memoryBacking>
+    <hugepages>
+      <page size='4' unit='KiB'/>
+    </hugepages>
+  </memoryBacking>
+  <vcpu placement='static'>2</vcpu>
+  <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</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
index 9e3906884decb2f78a0a8a3b4abb53c7767cff46..bce88a84a9fb59eb573f3840b840489380aed95d 100644 (file)
@@ -713,6 +713,7 @@ mymain(void)
     DO_TEST_FAILURE("hugepages-pages4", QEMU_CAPS_MEM_PATH,
             QEMU_CAPS_OBJECT_MEMORY_RAM, QEMU_CAPS_OBJECT_MEMORY_FILE);
     DO_TEST("hugepages-pages5", QEMU_CAPS_MEM_PATH);
+    DO_TEST("hugepages-pages6", NONE);
     DO_TEST("nosharepages", QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_MEM_MERGE);
     DO_TEST("disk-cdrom", NONE);
     DO_TEST("disk-cdrom-network-http", QEMU_CAPS_KVM, QEMU_CAPS_DEVICE,