[libvirt] [PATCH] qemu: Add support for locking domain's memory pages

--- docs/formatdomain.html.in | 26 +++++++++++++--------- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 20 +++++++++-------- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 11 +++++++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-off.args | 4 ++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-off.xml | 15 +++++++++++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-on.args | 4 ++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml | 18 +++++++++++++++ .../qemuxml2argv-mlock-unsupported.args | 4 ++++ .../qemuxml2argv-mlock-unsupported.xml | 15 +++++++++++++ tests/qemuxml2argvtest.c | 5 +++++ 14 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-mlock-off.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-mlock-off.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-mlock-on.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 5e89a92..da35d48 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -595,22 +595,28 @@ <memoryBacking> <hugepages/> <nosharepages/> + <locked/> </memoryBacking> ... </domain> </pre> + <p>The optional <code>memoryBacking</code> element may contain several + elements that influence how virtual memory pages are backed by host + pages.</p> + <dl> - <dt><code>memoryBacking</code></dt> - <dd>The optional <code>memoryBacking</code> element has two - optional elements. The element <code>hugepages</code> tells - the hypervisor that the guest should have its memory allocated - using hugepages instead of the normal native page size. And the - optional element <code>nosharepages</code> - (<span class="since">since 1.0.6</span>) tells the hypervisor - that share pages (memory merge, KSM) should be disabled on guest - startup. - </dd> + <dt><code>hugepages</code></dt> + <dd>This tells the hypervisor that the guest should have its memory + allocated using hugepages instead of the normal native page size.</dd> + <dt><code>nosharepages</code></dt> + <dd>Instructs hypervisor to disable shared pages (memory merge, KSM) for + this domain. <span class="since">Since 1.0.6</span></dd> + <dt><code>locked</code></dt> + <dd>When set and supported by the hypervisor, memory pages belonging + to the domain will be locked in host's memory and the host will not + be allowed to swap them out. + <span class="since">Since 1.0.6</span></dd> </dl> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 361794e..f3d3560 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -501,6 +501,11 @@ <empty/> </element> </optional> + <optional> + <element name="locked"> + <empty/> + </element> + </optional> </interleave> </element> </optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f0ca9d5..6d8e580 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10389,6 +10389,9 @@ virDomainDefParseXML(xmlDocPtr xml, if ((node = virXPathNode("./memoryBacking/nosharepages", ctxt))) def->mem.nosharepages = true; + if (virXPathBoolean("boolean(./memoryBacking/locked)", ctxt)) + def->mem.locked = true; + /* Extract blkio cgroup tunables */ if (virXPathUInt("string(./blkiotune/weight)", ctxt, &def->blkio.weight) < 0) @@ -15736,17 +15739,16 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->mem.swap_hard_limit) virBufferAddLit(buf, " </memtune>\n"); - if (def->mem.hugepage_backed || def->mem.nosharepages) + if (def->mem.hugepage_backed || def->mem.nosharepages || def->mem.locked) { virBufferAddLit(buf, " <memoryBacking>\n"); - - if (def->mem.hugepage_backed) - virBufferAddLit(buf, " <hugepages/>\n"); - - if (def->mem.nosharepages) - virBufferAddLit(buf, " <nosharepages/>\n"); - - if (def->mem.hugepage_backed || def->mem.nosharepages) + if (def->mem.hugepage_backed) + virBufferAddLit(buf, " <hugepages/>\n"); + if (def->mem.nosharepages) + virBufferAddLit(buf, " <nosharepages/>\n"); + if (def->mem.locked) + virBufferAddLit(buf, " <locked/>\n"); virBufferAddLit(buf, " </memoryBacking>\n"); + } virBufferAddLit(buf, " <vcpu"); virBufferAsprintf(buf, " placement='%s'", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c176a4c..16eb8b6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1861,6 +1861,7 @@ struct _virDomainDef { unsigned long long cur_balloon; /* in kibibytes */ bool hugepage_backed; bool nosharepages; + bool locked; int dump_core; /* enum virDomainMemDump */ unsigned long long hard_limit; /* in kibibytes */ unsigned long long soft_limit; /* in kibibytes */ diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 488cbfe..82129a2 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -230,6 +230,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "mem-merge", "vnc-websocket", "drive-discard", + "mlock", ); struct _virQEMUCaps { @@ -2246,6 +2247,7 @@ struct virQEMUCapsCommandLineProps { static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { { "machine", "mem-merge", QEMU_CAPS_MEM_MERGE }, { "drive", "discard", QEMU_CAPS_DRIVE_DISCARD }, + { "realtime", "mlock", QEMU_CAPS_MLOCK }, }; static int diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 173ca77..117bf8a 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -187,6 +187,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_MEM_MERGE = 146, /* -machine mem-merge */ QEMU_CAPS_VNC_WEBSOCKET = 147, /* -vnc x:y,websocket */ QEMU_CAPS_DRIVE_DISCARD = 148, /* -drive discard=off(ignore)|on(unmap) */ + QEMU_CAPS_MLOCK = 149, /* -realtime mlock=on|off */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5b95c07..c268a3a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6541,6 +6541,17 @@ qemuBuildCommandLine(virConnectPtr conn, cfg->hugepagePath, NULL); } + if (def->mem.locked && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_MLOCK)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("memory locking not supported by QEMU binary")); + goto error; + } + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MLOCK)) { + virCommandAddArg(cmd, "-realtime"); + virCommandAddArgFormat(cmd, "mlock=%s", + def->mem.locked ? "on" : "off"); + } + virCommandAddArg(cmd, "-smp"); if (!(smp = qemuBuildSmpArgStr(def, qemuCaps))) goto error; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-mlock-off.args b/tests/qemuxml2argvdata/qemuxml2argv-mlock-off.args new file mode 100644 index 0000000..2a5d94c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-mlock-off.args @@ -0,0 +1,4 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \ +/usr/bin/qemu -S -M pc -m 214 -realtime mlock=off \ +-smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -usb -net none -serial none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-mlock-off.xml b/tests/qemuxml2argvdata/qemuxml2argv-mlock-off.xml new file mode 100644 index 0000000..4125ca5 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-mlock-off.xml @@ -0,0 +1,15 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <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> + <devices> + <emulator>/usr/bin/qemu</emulator> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.args b/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.args new file mode 100644 index 0000000..bb6de13 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.args @@ -0,0 +1,4 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \ +/usr/bin/qemu -S -M pc -m 214 -realtime mlock=on \ +-smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -usb -net none -serial none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml b/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml new file mode 100644 index 0000000..20a5eaa --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml @@ -0,0 +1,18 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <devices> + <emulator>/usr/bin/qemu</emulator> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.args b/tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.args new file mode 100644 index 0000000..54dd3b9 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.args @@ -0,0 +1,4 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \ +/usr/bin/qemu -S -M pc -m 214 \ +-smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -usb -net none -serial none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.xml b/tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.xml new file mode 100644 index 0000000..4125ca5 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-mlock-unsupported.xml @@ -0,0 +1,15 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <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> + <devices> + <emulator>/usr/bin/qemu</emulator> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c751440..d853308 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1007,6 +1007,11 @@ mymain(void) QEMU_CAPS_DEVICE_SCSI_GENERIC, QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX); + DO_TEST("mlock-on", QEMU_CAPS_MLOCK); + DO_TEST_FAILURE("mlock-on", NONE); + DO_TEST("mlock-off", QEMU_CAPS_MLOCK); + DO_TEST("mlock-unsupported", NONE); + virObjectUnref(driver.config); virObjectUnref(driver.caps); virObjectUnref(driver.xmlopt); -- 1.8.2.1

On 05/16/2013 06:41 AM, Jiri Denemark wrote:
--- docs/formatdomain.html.in | 26 +++++++++++++--------- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 20 +++++++++-------- src/conf/domain_conf.h | 1 +
Can we split this into two patches; one that adds the new XML (and documents in the commit message what it looks like),
src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 11 +++++++++
...and one that implements the new feature in qemu?
tests/qemuxml2argvdata/qemuxml2argv-mlock-off.args | 4 ++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-off.xml | 15 +++++++++++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-on.args | 4 ++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml | 18 +++++++++++++++ .../qemuxml2argv-mlock-unsupported.args | 4 ++++ .../qemuxml2argv-mlock-unsupported.xml | 15 +++++++++++++ tests/qemuxml2argvtest.c | 5 +++++
I'm not sure how the tests are best split between the two patches, as long as 'make check' passes across both patches. ACK. The patch itself didn't have anything that caught my eye, other than my request to split it into functional pieces. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
participants (2)
-
Eric Blake
-
Jiri Denemark