To enable memory hotplug the maximum memory size and slot count need to
be specified. As qemu supports now other units than mebibytes when
specifying memory, use the new interface in this case.
---
docs/formatdomain.html.in | 2 +-
src/qemu/qemu_command.c | 41 ++++++++++++++++++----
src/qemu/qemu_domain.c | 4 ---
.../qemuxml2argv-memory-hotplug-nonuma.xml | 22 ++++++++++++
.../qemuxml2argv-memory-hotplug.args | 6 ++++
.../qemuxml2argv-memory-hotplug.xml | 34 ++++++++++++++++++
tests/qemuxml2argvtest.c | 4 +++
tests/qemuxml2xmltest.c | 3 ++
8 files changed, 105 insertions(+), 11 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug-nonuma.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 12f7ede..c059195 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -713,7 +713,7 @@
Note that due to alignment of the memory chunks added via memory
hotplug the full size allocation specified by this element may be
impossible to achieve.
- <span class='since'>Since 1.2.12</span>
+ <span class='since'>Since 1.2.12 supported by the QEMU
driver.</span>
</dd>
<dt><code>currentMemory</code></dt>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ec4f35b..5820fb5 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8230,14 +8230,43 @@ qemuBuildCommandLine(virConnectPtr conn,
if (qemuBuildDomainLoaderCommandLine(cmd, def, qemuCaps) < 0)
goto error;
- /* Set '-m MB' based on maxmem, because the lower 'memory' limit
- * is set post-startup using the balloon driver. If balloon driver
- * is not supported, then they're out of luck anyway. Update the
- * XML to reflect our rounding.
- */
virCommandAddArg(cmd, "-m");
+ /* Update config to reflect our rounding of memory size as we
+ * specify it in mebibytes. */
def->mem.max_balloon = VIR_DIV_UP(def->mem.max_balloon, 1024) * 1024;
- virCommandAddArgFormat(cmd, "%llu", def->mem.max_balloon / 1024);
+
+ if (def->mem.max_memory || def->mem.memory_slots) {
+ /* round this to the nearest mebibyte, qemu requires at least alignment
+ * in 4KiB (page size) blocks */
+ def->mem.max_memory = VIR_DIV_UP(def->mem.max_memory, 1024) * 1024;
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PC_DIMM)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("memory hotplug isn't supported by this QEMU
binary"));
+ goto error;
+ }
+
+ /* due to guest support, qemu would silently enable NUMA with one node
+ * once the memory hotplug backend is enabled. To avoid possible
+ * confusion we will enforce user originated numa configuration along
+ * with memory hotplug. */
+ if (!def->cpu || def->cpu->ncells == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("At least one numa node has to be configured when
"
+ "enabling memory hotplug"));
+ goto error;
+ }
+
+ /* Use the 'k' suffix to let qemu handle the units */
+ virCommandAddArgFormat(cmd, "size=%lluk,slots=%u,maxmem=%lluk",
+ def->mem.max_balloon,
+ def->mem.memory_slots,
+ def->mem.max_memory);
+
+ } else {
+ virCommandAddArgFormat(cmd, "%llu", def->mem.max_balloon / 1024);
+ }
+
if (def->mem.nhugepages && (!def->cpu || !def->cpu->ncells)) {
const long system_page_size = sysconf(_SC_PAGESIZE) / 1024;
char *mem_path = NULL;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 085bc81..99c46d4 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1040,10 +1040,6 @@ qemuDomainDefPostParse(virDomainDefPtr def,
VIR_DOMAIN_INPUT_BUS_USB) < 0)
return -1;
- /* memory hotplug tunables are not supported by this driver */
- if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
- return -1;
-
return 0;
}
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug-nonuma.xml
b/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug-nonuma.xml
new file mode 100644
index 0000000..5c807ed
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug-nonuma.xml
@@ -0,0 +1,22 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <maxMemory slots='9' unit='KiB'>1233456789</maxMemory>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</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>
+ <controller type='usb' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.args
b/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.args
new file mode 100644
index 0000000..6c26586
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.args
@@ -0,0 +1,6 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc \
+-m size=219136k,slots=16,maxmem=1099511627776k \
+-smp 2 -numa node,nodeid=0,cpus=0-1,mem=214 \
+-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-memory-hotplug.xml
b/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.xml
new file mode 100644
index 0000000..567a662
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.xml
@@ -0,0 +1,34 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <maxMemory slots='16' unit='KiB'>1099511627776</maxMemory>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static' cpuset='0-1'>2</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <cpu>
+ <topology sockets='2' cores='1' threads='1'/>
+ <numa>
+ <cell id='0' cpus='0-1' memory='219136'
unit='KiB'/>
+ </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>
+ <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='ide' index='0'/>
+ <controller type='usb' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 89afa81..2bc0ff3 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1517,6 +1517,10 @@ mymain(void)
DO_TEST_PARSE_ERROR("shmem-msi-only", NONE);
DO_TEST("cpu-host-passthrough-features", QEMU_CAPS_KVM,
QEMU_CAPS_CPU_HOST);
+ DO_TEST_FAILURE("memory-hotplug-nonuma", QEMU_CAPS_DEVICE_PC_DIMM);
+ DO_TEST_FAILURE("memory-hotplug", 0);
+ DO_TEST("memory-hotplug", QEMU_CAPS_DEVICE_PC_DIMM, QEMU_CAPS_NUMA);
+
virObjectUnref(driver.config);
virObjectUnref(driver.caps);
virObjectUnref(driver.xmlopt);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index f12983c..e840d63 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -418,6 +418,9 @@ mymain(void)
DO_TEST("shmem");
DO_TEST("smbios");
+ DO_TEST("memory-hotplug");
+ DO_TEST("memory-hotplug-nonuma");
+
virObjectUnref(driver.caps);
virObjectUnref(driver.xmlopt);
--
2.2.2