From 311b4a677f60cc1a3a29c525a703b31ec47d95b5 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Fri, 12 Dec 2014 10:37:35 +0100 Subject: [PATCH] qemu: Allow system pages to 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: 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 --- src/qemu/qemu_command.c | 84 +++++++++++-------- .../qemuxml2argv-hugepages-pages6.args | 4 + .../qemuxml2argv-hugepages-pages6.xml | 32 +++++++ tests/qemuxml2argvtest.c | 1 + 4 files changed, 87 insertions(+), 34 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 48bdf4ebe4..c44560f299 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -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 (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; + 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 (!(mem_path = qemuGetDefaultHugepath(cfg->hugetlbfs, - cfg->nhugetlbfs))) + 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 (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 index 0000000000..4eccb86e95 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.args @@ -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 index 0000000000..4f318fdf66 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages6.xml @@ -0,0 +1,32 @@ + + SomeDummyHugepagesGuest + ef1bdff4-27f3-4e85-a807-5fb4d58463cc + 1048576 + 1048576 + + + + + + 2 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 9e3906884d..bce88a84a9 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -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,