[libvirt] [PATCH v2 0/7] Memory locking fixes

Changes from [v1]: * exit early from the loop in patch 2; * dropped patch 5/8, as it's no longer needed; * rewrote tests not to generate QEMU command line; * changed documentation slightly. [v1] https://www.redhat.com/archives/libvir-list/2017-March/msg01089.html Andrea Bolognani (7): Revert "qemu: Forbid <memoryBacking><locked> without <memtune><hard_limit>" qemu: Remove qemuDomainRequiresMemLock() qemu: Fix memory locking limit calculation process: Translate "unlimited" correctly tests: Introduce virTestCompareToULL() tests: Introduce QEMU memory locking limit tests docs: Improve documentation related to memory locking docs/formatdomain.html.in | 39 ++++-- src/qemu/qemu_command.c | 4 +- src/qemu/qemu_domain.c | 76 ++++------ src/qemu/qemu_domain.h | 1 - src/util/virprocess.c | 20 ++- tests/Makefile.am | 9 ++ .../qemumemlock-pc-hardlimit+hostdev.xml | 20 +++ .../qemumemlock-pc-hardlimit+locked+hostdev.xml | 23 ++++ .../qemumemlock-pc-hardlimit+locked.xml | 17 +++ tests/qemumemlockdata/qemumemlock-pc-hardlimit.xml | 14 ++ tests/qemumemlockdata/qemumemlock-pc-hostdev.xml | 17 +++ tests/qemumemlockdata/qemumemlock-pc-kvm.xml | 11 ++ .../qemumemlock-pc-locked+hostdev.xml | 20 +++ tests/qemumemlockdata/qemumemlock-pc-locked.xml | 14 ++ tests/qemumemlockdata/qemumemlock-pc-tcg.xml | 11 ++ .../qemumemlock-pseries-hardlimit+hostdev.xml | 20 +++ ...emumemlock-pseries-hardlimit+locked+hostdev.xml | 23 ++++ .../qemumemlock-pseries-hardlimit+locked.xml | 17 +++ .../qemumemlock-pseries-hardlimit.xml | 14 ++ .../qemumemlock-pseries-hostdev.xml | 17 +++ tests/qemumemlockdata/qemumemlock-pseries-kvm.xml | 11 ++ .../qemumemlock-pseries-locked+hostdev.xml | 20 +++ .../qemumemlockdata/qemumemlock-pseries-locked.xml | 14 ++ tests/qemumemlockdata/qemumemlock-pseries-tcg.xml | 11 ++ tests/qemumemlocktest.c | 153 +++++++++++++++++++++ tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml | 3 - tests/testutils.c | 27 ++++ tests/testutils.h | 2 + 28 files changed, 556 insertions(+), 72 deletions(-) create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-kvm.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-tcg.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-kvm.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-tcg.xml create mode 100644 tests/qemumemlocktest.c -- 2.7.4

This reverts commit c2e60ad0e5124482942164e5fec088157f5e716a. Turns out this check is excessively strict: there are ways other than <memtune><hard_limit> to raise the memory locking limit for QEMU processes, one prominent example being tweaking /etc/security/limits.conf. Partially-resolves: https://bugzilla.redhat.com/1431793 --- src/qemu/qemu_domain.c | 10 ---------- tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml | 3 --- 2 files changed, 13 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 20999cd..041126b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2922,16 +2922,6 @@ qemuDomainDefValidate(const virDomainDef *def, } } - /* Memory locking can only work properly if the memory locking limit - * for the QEMU process has been raised appropriately: the default one - * is extrememly low, so there's no way the guest will fit in there */ - if (def->mem.locked && !virMemoryLimitIsSet(def->mem.hard_limit)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Setting <memoryBacking><locked> requires " - "<memtune><hard_limit> to be set as well")); - goto cleanup; - } - if (qemuDomainDefValidateVideo(def) < 0) goto cleanup; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml b/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml index 2046663..20a5eaa 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-mlock-on.xml @@ -3,9 +3,6 @@ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> <memory unit='KiB'>219136</memory> <currentMemory unit='KiB'>219136</currentMemory> - <memtune> - <hard_limit unit='KiB'>256000</hard_limit> - </memtune> <memoryBacking> <locked/> </memoryBacking> -- 2.7.4

Instead of having a separate function, we can simply return zero from the existing qemuDomainGetMemLockLimitBytes() to signal the caller that the memory locking limit doesn't need to be set for the guest. Having a single function instead of two makes it less likely that we will use the wrong value, which is exactly what happened when we started applying the limit that was meant for VFIO-using guests to <memoryBacking><locked>-using guests. --- src/qemu/qemu_command.c | 4 +--- src/qemu/qemu_domain.c | 63 +++++++++++++++++++------------------------------ src/qemu/qemu_domain.h | 1 - 3 files changed, 25 insertions(+), 43 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2045c2e..52f6e00 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9740,7 +9740,6 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); unsigned int bootHostdevNet = 0; - VIR_DEBUG("driver=%p def=%p mon=%p json=%d " "qemuCaps=%p migrateURI=%s snapshot=%p vmop=%d", driver, def, monitor_chr, monitor_json, @@ -9966,8 +9965,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, /* In some situations, eg. VFIO passthrough, QEMU might need to lock a * significant amount of memory, so we need to set the limit accordingly */ - if (qemuDomainRequiresMemLock(def)) - virCommandSetMaxMemLock(cmd, qemuDomainGetMemLockLimitBytes(def)); + virCommandSetMaxMemLock(cmd, qemuDomainGetMemLockLimitBytes(def)); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSG_TIMESTAMP) && cfg->logTimestamp) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 041126b..b098626 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -6202,18 +6202,20 @@ qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver, /** * qemuDomainGetMemLockLimitBytes: - * * @def: domain definition * - * Returns the size of the memory in bytes that needs to be set as - * RLIMIT_MEMLOCK for the QEMU process. - * If a mem.hard_limit is set, then that value is preferred; otherwise, the - * value returned may depend upon the architecture or devices present. + * Calculate the memory locking limit that needs to be set in order for + * the guest to operate properly. The limit depends on a number of factors, + * including certain configuration options and less immediately apparent ones + * such as the guest architecture or the use of certain devices. + * + * Returns: the memory locking limit, or 0 if setting the limit is not needed */ unsigned long long qemuDomainGetMemLockLimitBytes(virDomainDefPtr def) { - unsigned long long memKB; + unsigned long long memKB = 0; + size_t i; /* prefer the hard limit */ if (virMemoryLimitIsSet(def->mem.hard_limit)) { @@ -6221,13 +6223,17 @@ qemuDomainGetMemLockLimitBytes(virDomainDefPtr def) goto done; } - if (ARCH_IS_PPC64(def->os.arch)) { + if (def->mem.locked) { + memKB = virDomainDefGetMemoryTotal(def) + 1024 * 1024; + goto done; + } + + if (ARCH_IS_PPC64(def->os.arch) && def->virtType == VIR_DOMAIN_VIRT_KVM) { unsigned long long maxMemory; unsigned long long memory; unsigned long long baseLimit; unsigned long long passthroughLimit; size_t nPCIHostBridges; - size_t i; bool usesVFIO = false; /* TODO: Detect at runtime once we start using more than just @@ -6317,44 +6323,22 @@ qemuDomainGetMemLockLimitBytes(virDomainDefPtr def) * * Note that this may not be valid for all platforms. */ - memKB = virDomainDefGetMemoryTotal(def) + 1024 * 1024; - - done: - return memKB << 10; -} - - -/** - * @def: domain definition - * - * Returns true if the locked memory limit needs to be set or updated because - * of domain configuration, VFIO passthrough devices or architecture-specific - * requirements. - * */ -bool -qemuDomainRequiresMemLock(virDomainDefPtr def) -{ - size_t i; - - if (def->mem.locked) - return true; - for (i = 0; i < def->nhostdevs; i++) { virDomainHostdevDefPtr dev = def->hostdevs[i]; if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) - return true; + dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + memKB = virDomainDefGetMemoryTotal(def) + 1024 * 1024; + goto done; + } } - /* ppc64 KVM domains need to lock some memory even when VFIO is not used */ - if (ARCH_IS_PPC64(def->os.arch) && def->virtType == VIR_DOMAIN_VIRT_KVM) - return true; - - return false; + done: + return memKB << 10; } + /** * qemuDomainAdjustMaxMemLock: * @vm: domain @@ -6375,7 +6359,9 @@ qemuDomainAdjustMaxMemLock(virDomainObjPtr vm) unsigned long long bytes = 0; int ret = -1; - if (qemuDomainRequiresMemLock(vm->def)) { + bytes = qemuDomainGetMemLockLimitBytes(vm->def); + + if (bytes) { /* If this is the first time adjusting the limit, save the current * value so that we can restore it once memory locking is no longer * required. Failing to obtain the current limit is not a critical @@ -6384,7 +6370,6 @@ qemuDomainAdjustMaxMemLock(virDomainObjPtr vm) if (virProcessGetMaxMemLock(vm->pid, &(vm->original_memlock)) < 0) vm->original_memlock = 0; } - bytes = qemuDomainGetMemLockLimitBytes(vm->def); } else { /* Once memory locking is no longer required, we can restore the * original, usually very low, limit */ diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 36e3a85..8273f10 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -690,7 +690,6 @@ int qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver, virDomainObjPtr vm); unsigned long long qemuDomainGetMemLockLimitBytes(virDomainDefPtr def); -bool qemuDomainRequiresMemLock(virDomainDefPtr def); int qemuDomainAdjustMaxMemLock(virDomainObjPtr vm); int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, -- 2.7.4

For guests that use <memoryBacking><locked>, our only option is to remove the memory locking limit altogether. Partially-resolves: https://bugzilla.redhat.com/1431793 --- src/qemu/qemu_domain.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b098626..0e35000 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -6223,10 +6223,13 @@ qemuDomainGetMemLockLimitBytes(virDomainDefPtr def) goto done; } - if (def->mem.locked) { - memKB = virDomainDefGetMemoryTotal(def) + 1024 * 1024; - goto done; - } + /* If the guest wants its memory to be locked, we need to raise the memory + * locking limit so that the OS will not refuse allocation requests; + * however, there is no reliable way for us to figure out how much memory + * the QEMU process will allocate for its own use, so our only way out is + * to remove the limit altogether. Use with extreme care */ + if (def->mem.locked) + return VIR_DOMAIN_MEMORY_PARAM_UNLIMITED; if (ARCH_IS_PPC64(def->os.arch) && def->virtType == VIR_DOMAIN_VIRT_KVM) { unsigned long long maxMemory; -- 2.7.4

The value we use internally to represent the lack of a memory locking limit, VIR_DOMAIN_MEMORY_PARAM_UNLIMITED, doesn't match the value setrlimit() and prlimit() use for the same purpose, RLIM_INFINITY, so we have to handle the translation ourselves. Partially-resolves: https://bugzilla.redhat.com/1431793 --- src/util/virprocess.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/util/virprocess.c b/src/util/virprocess.c index 16eb412..1fbbbb3 100644 --- a/src/util/virprocess.c +++ b/src/util/virprocess.c @@ -747,7 +747,15 @@ virProcessSetMaxMemLock(pid_t pid, unsigned long long bytes) if (bytes == 0) return 0; - rlim.rlim_cur = rlim.rlim_max = bytes; + /* We use VIR_DOMAIN_MEMORY_PARAM_UNLIMITED internally to represent + * unlimited memory amounts, but setrlimit() and prlimit() use + * RLIM_INFINITY for the same purpose, so we need to translate between + * the two conventions */ + if (virMemoryLimitIsSet(bytes)) + rlim.rlim_cur = rlim.rlim_max = bytes; + else + rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; + if (pid == 0) { if (setrlimit(RLIMIT_MEMLOCK, &rlim) < 0) { virReportSystemError(errno, @@ -810,8 +818,14 @@ virProcessGetMaxMemLock(pid_t pid, } /* virProcessSetMaxMemLock() sets both rlim_cur and rlim_max to the - * same value, so we can retrieve just rlim_max here */ - *bytes = rlim.rlim_max; + * same value, so we can retrieve just rlim_max here. We use + * VIR_DOMAIN_MEMORY_PARAM_UNLIMITED internally to represent unlimited + * memory amounts, but setrlimit() and prlimit() use RLIM_INFINITY for the + * same purpose, so we need to translate between the two conventions */ + if (rlim.rlim_max == RLIM_INFINITY) + *bytes = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED; + else + *bytes = rlim.rlim_max; return 0; } -- 2.7.4

This will be used later on in the test suite. --- tests/testutils.c | 27 +++++++++++++++++++++++++++ tests/testutils.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/tests/testutils.c b/tests/testutils.c index 13eff9e..f3feb6d 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -722,6 +722,33 @@ virTestCompareToFile(const char *strcontent, } /* + * @param content: Input content + * @param src: Source to compare @content against + */ +int +virTestCompareToULL(unsigned long long content, + unsigned long long src) +{ + char *strcontent = NULL; + char *strsrc = NULL; + int ret = -1; + + if (virAsprintf(&strcontent, "%llu", content) < 0) + goto cleanup; + + if (virAsprintf(&strsrc, "%llu", src) < 0) + goto cleanup; + + ret = virTestCompareToString(strcontent, strsrc); + + cleanup: + VIR_FREE(strcontent); + VIR_FREE(strsrc); + + return ret; +} + +/* * @param strcontent: String input content * @param strsrc: String source to compare strcontent against */ diff --git a/tests/testutils.h b/tests/testutils.h index c7c641c..c16fe6c 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -77,6 +77,8 @@ int virTestCompareToFile(const char *strcontent, const char *filename); int virTestCompareToString(const char *strcontent, const char *strsrc); +int virTestCompareToULL(unsigned long long content, + unsigned long long src); unsigned int virTestGetDebug(void); unsigned int virTestGetVerbose(void); -- 2.7.4

These tests cover a number of scenarios where we care about the memory locking limit being set correctly for the guest to work properly. --- tests/Makefile.am | 9 ++ .../qemumemlock-pc-hardlimit+hostdev.xml | 20 +++ .../qemumemlock-pc-hardlimit+locked+hostdev.xml | 23 ++++ .../qemumemlock-pc-hardlimit+locked.xml | 17 +++ tests/qemumemlockdata/qemumemlock-pc-hardlimit.xml | 14 ++ tests/qemumemlockdata/qemumemlock-pc-hostdev.xml | 17 +++ tests/qemumemlockdata/qemumemlock-pc-kvm.xml | 11 ++ .../qemumemlock-pc-locked+hostdev.xml | 20 +++ tests/qemumemlockdata/qemumemlock-pc-locked.xml | 14 ++ tests/qemumemlockdata/qemumemlock-pc-tcg.xml | 11 ++ .../qemumemlock-pseries-hardlimit+hostdev.xml | 20 +++ ...emumemlock-pseries-hardlimit+locked+hostdev.xml | 23 ++++ .../qemumemlock-pseries-hardlimit+locked.xml | 17 +++ .../qemumemlock-pseries-hardlimit.xml | 14 ++ .../qemumemlock-pseries-hostdev.xml | 17 +++ tests/qemumemlockdata/qemumemlock-pseries-kvm.xml | 11 ++ .../qemumemlock-pseries-locked+hostdev.xml | 20 +++ .../qemumemlockdata/qemumemlock-pseries-locked.xml | 14 ++ tests/qemumemlockdata/qemumemlock-pseries-tcg.xml | 11 ++ tests/qemumemlocktest.c | 153 +++++++++++++++++++++ 20 files changed, 456 insertions(+) create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hardlimit.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-kvm.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pc-tcg.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hardlimit.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-kvm.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-locked.xml create mode 100644 tests/qemumemlockdata/qemumemlock-pseries-tcg.xml create mode 100644 tests/qemumemlocktest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 076734f..db5e475 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -127,6 +127,7 @@ EXTRA_DIST = \ qemumonitorjsondata \ qemuxml2argvdata \ qemuxml2xmloutdata \ + qemumemlockdata \ secretxml2xmlin \ securityselinuxhelperdata \ securityselinuxlabeldata \ @@ -277,6 +278,7 @@ test_programs += qemuxml2argvtest qemuxml2xmltest \ qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest \ qemumonitortest qemumonitorjsontest qemuhotplugtest \ qemuagenttest qemucapabilitiestest qemucaps2xmltest \ + qemumemlocktest \ qemucommandutiltest test_helpers += qemucapsprobe test_libraries += libqemumonitortestutils.la \ @@ -659,6 +661,12 @@ domainsnapshotxml2xmltest_SOURCES = \ domainsnapshotxml2xmltest.c testutilsqemu.c testutilsqemu.h \ testutils.c testutils.h domainsnapshotxml2xmltest_LDADD = $(qemu_LDADDS) $(LDADDS) + +qemumemlocktest_SOURCES = \ + qemumemlocktest.c \ + testutilsqemu.c testutilsqemu.h \ + testutils.c testutils.h +qemumemlocktest_LDADD = $(qemu_LDADDS) $(LDADDS) else ! WITH_QEMU EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \ qemuhelptest.c domainsnapshotxml2xmltest.c \ @@ -666,6 +674,7 @@ EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \ qemumonitorjsontest.c qemuhotplugtest.c \ qemuagenttest.c qemucapabilitiestest.c \ qemucaps2xmltest.c qemucommandutiltest.c \ + qemumemlocktest.c \ $(QEMUMONITORTESTUTILS_SOURCES) endif ! WITH_QEMU diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml new file mode 100644 index 0000000..5443145 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml @@ -0,0 +1,20 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml new file mode 100644 index 0000000..8184eef --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml @@ -0,0 +1,23 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked.xml new file mode 100644 index 0000000..78bee62 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked.xml @@ -0,0 +1,17 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit.xml new file mode 100644 index 0000000..b1e3867 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit.xml @@ -0,0 +1,14 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml new file mode 100644 index 0000000..6c058a9 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml @@ -0,0 +1,17 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-kvm.xml b/tests/qemumemlockdata/qemumemlock-pc-kvm.xml new file mode 100644 index 0000000..7fa4e24 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-kvm.xml @@ -0,0 +1,11 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml new file mode 100644 index 0000000..fbc1dc3 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml @@ -0,0 +1,20 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-locked.xml b/tests/qemumemlockdata/qemumemlock-pc-locked.xml new file mode 100644 index 0000000..febb036 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-locked.xml @@ -0,0 +1,14 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pc-tcg.xml b/tests/qemumemlockdata/qemumemlock-pc-tcg.xml new file mode 100644 index 0000000..1934269 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pc-tcg.xml @@ -0,0 +1,11 @@ +<domain type='qemu'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml new file mode 100644 index 0000000..ddd3b47 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml @@ -0,0 +1,20 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml new file mode 100644 index 0000000..73c28c1 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml @@ -0,0 +1,23 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked.xml new file mode 100644 index 0000000..fe984a2 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked.xml @@ -0,0 +1,17 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit.xml new file mode 100644 index 0000000..b23de1d --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit.xml @@ -0,0 +1,14 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memtune> + <hard_limit unit='KiB'>2097152</hard_limit> + </memtune> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml new file mode 100644 index 0000000..daf70a4 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml @@ -0,0 +1,17 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-kvm.xml b/tests/qemumemlockdata/qemumemlock-pseries-kvm.xml new file mode 100644 index 0000000..5a065da --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-kvm.xml @@ -0,0 +1,11 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml new file mode 100644 index 0000000..74212f1 --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml @@ -0,0 +1,20 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-locked.xml b/tests/qemumemlockdata/qemumemlock-pseries-locked.xml new file mode 100644 index 0000000..befaefd --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-locked.xml @@ -0,0 +1,14 @@ +<domain type='kvm'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <memoryBacking> + <locked/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-tcg.xml b/tests/qemumemlockdata/qemumemlock-pseries-tcg.xml new file mode 100644 index 0000000..a3b03dd --- /dev/null +++ b/tests/qemumemlockdata/qemumemlock-pseries-tcg.xml @@ -0,0 +1,11 @@ +<domain type='qemu'> + <name>guest</name> + <memory unit='KiB'>1048576</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + </devices> +</domain> diff --git a/tests/qemumemlocktest.c b/tests/qemumemlocktest.c new file mode 100644 index 0000000..9159388 --- /dev/null +++ b/tests/qemumemlocktest.c @@ -0,0 +1,153 @@ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <fcntl.h> + +#include "testutils.h" + +#ifdef WITH_QEMU + +# include "datatypes.h" +# include "internal.h" +# include "virstring.h" +# include "conf/domain_conf.h" +# include "qemu/qemu_domain.h" + +# include "testutilsqemu.h" + +# define VIR_FROM_THIS VIR_FROM_QEMU + +static const char *abs_top_srcdir; +static virQEMUDriver driver; + +struct testInfo { + const char *name; + unsigned long long memlock; +}; + +static int +testCompareMemLock(const void *data) +{ + const struct testInfo *info = data; + virConnectPtr conn = NULL; + virDomainObjPtr vm = NULL; + char *xml = NULL; + int ret = -1; + + if (!(conn = virGetConnect())) + goto cleanup; + + if (virAsprintf(&xml, "%s/qemumemlockdata/qemumemlock-%s.xml", + abs_srcdir, info->name) < 0) + goto cleanup; + + if (!(vm = virDomainObjNew(driver.xmlopt))) + goto cleanup; + + if (!(vm->def = virDomainDefParseFile(xml, driver.caps, driver.xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) { + goto cleanup; + } + + if (virTestCompareToULL(info->memlock, qemuDomainGetMemLockLimitBytes(vm->def)) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virObjectUnref(vm); + virObjectUnref(conn); + VIR_FREE(xml); + + return ret; +} + + +static int +mymain(void) +{ + int ret = 0; + + abs_top_srcdir = getenv("abs_top_srcdir"); + if (!abs_top_srcdir) + abs_top_srcdir = abs_srcdir "/.."; + + if (qemuTestDriverInit(&driver) < 0) + return EXIT_FAILURE; + + driver.privileged = true; + +# define DO_TEST(name, memlock) \ + do { \ + static struct testInfo info = { \ + name, memlock \ + }; \ + if (virTestRun("QEMU MEMLOCK " name, testCompareMemLock, &info) < 0) \ + ret = -1; \ + } while (0) + + /* The tests below make sure that the memory locking limit is being + * calculated correctly in a number of situations. Each test is + * performed both on x86_64/pc and ppc64/pseries in order to account + * for some architecture-specific details. + * + * kvm: simple KMV guest + * tcg: simple TCG guest + * + * hardlimit: guest where <memtune><hard_limit> has been configured + * locked: guest where <memoryBacking><locked> has been enabled + * hostdev: guest that has some hostdev assigned + * + * The remaining tests cover different combinations of the above to + * ensure settings are prioritized as expected. + */ + + qemuTestSetHostArch(driver.caps, VIR_ARCH_X86_64); + + DO_TEST("pc-kvm", 0); + DO_TEST("pc-tcg", 0); + + DO_TEST("pc-hardlimit", 2147483648); + DO_TEST("pc-locked", VIR_DOMAIN_MEMORY_PARAM_UNLIMITED); + DO_TEST("pc-hostdev", 2147483648); + + DO_TEST("pc-hardlimit+locked", 2147483648); + DO_TEST("pc-hardlimit+hostdev", 2147483648); + DO_TEST("pc-hardlimit+locked+hostdev", 2147483648); + DO_TEST("pc-locked+hostdev", VIR_DOMAIN_MEMORY_PARAM_UNLIMITED); + + qemuTestSetHostArch(driver.caps, VIR_ARCH_PPC64); + + DO_TEST("pseries-kvm", 20971520); + DO_TEST("pseries-tcg", 0); + + DO_TEST("pseries-hardlimit", 2147483648); + DO_TEST("pseries-locked", VIR_DOMAIN_MEMORY_PARAM_UNLIMITED); + DO_TEST("pseries-hostdev", 2168455168); + + DO_TEST("pseries-hardlimit+locked", 2147483648); + DO_TEST("pseries-hardlimit+hostdev", 2147483648); + DO_TEST("pseries-hardlimit+locked+hostdev", 2147483648); + DO_TEST("pseries-locked+hostdev", VIR_DOMAIN_MEMORY_PARAM_UNLIMITED); + + qemuTestDriverFree(&driver); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) + +#else + +int +main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /* WITH_QEMU */ -- 2.7.4

On Mon, Mar 27, 2017 at 05:38:58PM +0200, Andrea Bolognani wrote:
These tests cover a number of scenarios where we care about the memory locking limit being set correctly for the guest to work properly. ---
+static int +testCompareMemLock(const void *data) +{ + const struct testInfo *info = data; + virConnectPtr conn = NULL; + virDomainObjPtr vm = NULL; + char *xml = NULL; + int ret = -1; + + if (!(conn = virGetConnect())) + goto cleanup; + + if (virAsprintf(&xml, "%s/qemumemlockdata/qemumemlock-%s.xml", + abs_srcdir, info->name) < 0) + goto cleanup; + + if (!(vm = virDomainObjNew(driver.xmlopt))) + goto cleanup; + + if (!(vm->def = virDomainDefParseFile(xml, driver.caps, driver.xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) { + goto cleanup; + } + + if (virTestCompareToULL(info->memlock, qemuDomainGetMemLockLimitBytes(vm->def)) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virObjectUnref(vm); + virObjectUnref(conn); + VIR_FREE(xml); + + return ret; +} +
Looking at this function I don't think we really understood each other. Looks like I explain better with code than words, so let me fix that right up. ACK with the following squashed in: diff --git c/tests/qemumemlocktest.c w/tests/qemumemlocktest.c index 91593884656f..50e23d584e30 100644 --- c/tests/qemumemlocktest.c +++ w/tests/qemumemlocktest.c @@ -34,34 +34,23 @@ static int testCompareMemLock(const void *data) { const struct testInfo *info = data; - virConnectPtr conn = NULL; - virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; char *xml = NULL; int ret = -1; - if (!(conn = virGetConnect())) - goto cleanup; - if (virAsprintf(&xml, "%s/qemumemlockdata/qemumemlock-%s.xml", abs_srcdir, info->name) < 0) goto cleanup; - if (!(vm = virDomainObjNew(driver.xmlopt))) - goto cleanup; - - if (!(vm->def = virDomainDefParseFile(xml, driver.caps, driver.xmlopt, NULL, - VIR_DOMAIN_DEF_PARSE_INACTIVE))) { + if (!(def = virDomainDefParseFile(xml, driver.caps, driver.xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) { goto cleanup; } - if (virTestCompareToULL(info->memlock, qemuDomainGetMemLockLimitBytes(vm->def)) < 0) - goto cleanup; - - ret = 0; - + ret = virTestCompareToULL(info->memlock, + qemuDomainGetMemLockLimitBytes(def)); cleanup: - virObjectUnref(vm); - virObjectUnref(conn); + virDomainDefFree(def); VIR_FREE(xml); return ret; --

On Mon, 2017-03-27 at 22:15 +0200, Martin Kletzander wrote: [...]
Looking at this function I don't think we really understood each other. Looks like I explain better with code than words, so let me fix that right up. ACK with the following squashed in:
I understood your suggestion, I just did not realize the full extent to which I could get rid of superflous code ;) Once again, following your advice resulted in a much leaner and readable test case, which is great! Thanks a bunch :) -- Andrea Bolognani / Red Hat / Virtualization

--- docs/formatdomain.html.in | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4a3123e..180bca0 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -937,14 +937,21 @@ <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. For QEMU/KVM this requires - <code>hard_limit</code> <a href="#elementsMemoryTuning">memory tuning</a> - element to be used and set to the maximum memory configured for the - domain plus any memory consumed by the QEMU process itself. Beware of - setting the memory limit too high (and thus allowing the domain to lock - most of the host's memory). Doing so may be dangerous to both the - domain and the host itself since the host's kernel may run out of - memory. <span class="since">Since 1.0.6</span></dd> + be allowed to swap them out, which might be required for some + workloads such as real-time. For QEMU/KVM guests, the memory used by + the QEMU process itself will be locked too: unlike guest memory, this + is an amount libvirt has no way of figuring out in advance, so it has + to remove the limit on locked memory altogether. Thus, enabling this + option opens up to a potential security risk: the host will be unable + to reclaim the locked memory back from the guest when it's running out + of memory, which means a malicious guest allocating large amounts of + locked memory could cause a denial-of-service attach on the host. + Because of this, using this option is discouraged unless your workload + demands it; even then, it's highly recommended to set an + <code>hard_limit</code> (see + <a href="#elementsMemoryTuning">memory tuning</a>) on memory allocation + suitable for the specific environment at the same time to mitigate + the risks described above. <span class="since">Since 1.0.6</span></dd> <dt><code>source</code></dt> <dd>In this attribute you can switch to file memorybacking or keep default anonymous.</dd> <dt><code>access</code></dt> @@ -989,12 +996,18 @@ <dt><code>hard_limit</code></dt> <dd> The optional <code>hard_limit</code> element is the maximum memory the guest can use. The units for this value are kibibytes (i.e. blocks - of 1024 bytes). <strong>However, users of QEMU and KVM are strongly - advised not to set this limit as domain may get killed by the kernel - if the guess is too low. To determine the memory needed for a process - to run is an + of 1024 bytes). Users of QEMU and KVM are strongly advised not to set + this limit as domain may get killed by the kernel if the guess is too + low, and determining the memory needed for a process to run is an <a href="http://en.wikipedia.org/wiki/Undecidable_problem"> - undecidable problem</a>.</strong></dd> + undecidable problem</a>; that said, if you already set + <code>locked</code> in + <a href="#elementsMemoryBacking">memory backing</a> because your + workload demands it, you'll have to take into account the specifics of + your deployment and figure out a value for <code>hard_limit</code> that + balances the risk of your guest being killed because the limit was set + too low and the risk of your host crashing because it cannot reclaim + the memory used by the guest due to <code>locked</code>. Good luck!</dd> <dt><code>soft_limit</code></dt> <dd> The optional <code>soft_limit</code> element is the memory limit to enforce during memory contention. The units for this value are -- 2.7.4

On Mon, Mar 27, 2017 at 05:38:52PM +0200, Andrea Bolognani wrote:
Changes from [v1]:
* exit early from the loop in patch 2;
* dropped patch 5/8, as it's no longer needed;
* rewrote tests not to generate QEMU command line;
About that ^^ there's still something to fix, but if you follow my advice, ACK series.

On Mon, 2017-03-27 at 22:16 +0200, Martin Kletzander wrote:
About that ^^ there's still something to fix, but if you follow my advice, ACK series.
Thanks. Pushed on account of the fact that it was ACKed before the freeze started. -- Andrea Bolognani / Red Hat / Virtualization
participants (2)
-
Andrea Bolognani
-
Martin Kletzander