https://bugzilla.redhat.com/show_bug.cgi?id=1624223
There are two ways to request memory preallocation on cmd line:
-mem-prealloc and .prealloc attribute to memory-backend-file.
However, as it turns out it's not safe to use both at the same
time. Prefer -mem-prealloc as it is more backward compatible
compared to switching to "-numa node,memdev= + -object
memory-backend-file".
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_command.c | 37 +++++++++++++------
src/qemu/qemu_command.h | 1 +
src/qemu/qemu_domain.c | 2 +
src/qemu/qemu_domain.h | 3 ++
src/qemu/qemu_hotplug.c | 3 +-
.../hugepages-numa-default-dimm.args | 2 +-
6 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index e338d3172e..0294030f0e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3123,6 +3123,7 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd,
* @def: domain definition object
* @mem: memory definition object
* @autoNodeset: fallback nodeset in case of automatic NUMA placement
+ * @forbidPrealloc: don't set prealloc attribute
* @force: forcibly use one of the backends
*
* Creates a configuration object that represents memory backend of given guest
@@ -3136,6 +3137,9 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd,
* Then, if one of the two memory-backend-* should be used, the @qemuCaps is
* consulted to check if qemu does support it.
*
+ * If @forbidPrealloc is true then 'prealloc' attribute of the backend is not
+ * set. This may come handy when global -mem-prealloc is already specified.
+ *
* Returns: 0 on success,
* 1 on success and if there's no need to use memory-backend-*
* -1 on error.
@@ -3148,6 +3152,7 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
virDomainDefPtr def,
virDomainMemoryDefPtr mem,
virBitmapPtr autoNodeset,
+ bool forbidPrealloc,
bool force)
{
const char *backendType = "memory-backend-file";
@@ -3265,11 +3270,13 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
if (mem->nvdimmPath) {
if (VIR_STRDUP(memPath, mem->nvdimmPath) < 0)
goto cleanup;
- prealloc = true;
+ if (!forbidPrealloc)
+ prealloc = true;
} else if (useHugepage) {
if (qemuGetDomainHupageMemPath(def, cfg, pagesize, &memPath) < 0)
goto cleanup;
- prealloc = true;
+ if (!forbidPrealloc)
+ prealloc = true;
} else {
/* We can have both pagesize and mem source. If that's the case,
* prefer hugepages as those are more specific. */
@@ -3398,7 +3405,8 @@ qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
mem.info.alias = alias;
if ((rc = qemuBuildMemoryBackendProps(&props, alias, cfg, priv->qemuCaps,
- def, &mem, priv->autoNodeset, false))
< 0)
+ def, &mem, priv->autoNodeset,
+ priv->memPrealloc, false)) < 0)
goto cleanup;
if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
@@ -3435,7 +3443,8 @@ qemuBuildMemoryDimmBackendStr(virBufferPtr buf,
goto cleanup;
if (qemuBuildMemoryBackendProps(&props, alias, cfg, priv->qemuCaps,
- def, mem, priv->autoNodeset, true) < 0)
+ def, mem, priv->autoNodeset,
+ priv->memPrealloc, true) < 0)
goto cleanup;
if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
@@ -7443,7 +7452,8 @@ qemuBuildSmpCommandLine(virCommandPtr cmd,
static int
qemuBuildMemPathStr(virQEMUDriverConfigPtr cfg,
const virDomainDef *def,
- virCommandPtr cmd)
+ virCommandPtr cmd,
+ qemuDomainObjPrivatePtr priv)
{
const long system_page_size = virGetSystemPageSizeKB();
char *mem_path = NULL;
@@ -7465,8 +7475,10 @@ qemuBuildMemPathStr(virQEMUDriverConfigPtr cfg,
return 0;
}
- if (def->mem.allocation != VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE)
+ if (def->mem.allocation != VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
virCommandAddArgList(cmd, "-mem-prealloc", NULL);
+ priv->memPrealloc = true;
+ }
virCommandAddArgList(cmd, "-mem-path", mem_path, NULL);
VIR_FREE(mem_path);
@@ -7479,7 +7491,8 @@ static int
qemuBuildMemCommandLine(virCommandPtr cmd,
virQEMUDriverConfigPtr cfg,
const virDomainDef *def,
- virQEMUCapsPtr qemuCaps)
+ virQEMUCapsPtr qemuCaps,
+ qemuDomainObjPrivatePtr priv)
{
if (qemuDomainDefValidateMemoryHotplug(def, qemuCaps, NULL) < 0)
return -1;
@@ -7498,15 +7511,17 @@ qemuBuildMemCommandLine(virCommandPtr cmd,
virDomainDefGetMemoryInitial(def) / 1024);
}
- if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE)
+ if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
virCommandAddArgList(cmd, "-mem-prealloc", NULL);
+ priv->memPrealloc = true;
+ }
/*
* Add '-mem-path' (and '-mem-prealloc') parameter here if
* the hugepages and no numa node is specified.
*/
if (!virDomainNumaGetNodeCount(def->numa) &&
- qemuBuildMemPathStr(cfg, def, cmd) < 0)
+ qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
return -1;
if (def->mem.locked && !virQEMUCapsGet(qemuCaps,
QEMU_CAPS_REALTIME_MLOCK)) {
@@ -7613,7 +7628,7 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
}
if (!needBackend &&
- qemuBuildMemPathStr(cfg, def, cmd) < 0)
+ qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
goto cleanup;
for (i = 0; i < ncells; i++) {
@@ -10250,7 +10265,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
if (!migrateURI && !snapshot && qemuDomainAlignMemorySizes(def) <
0)
goto error;
- if (qemuBuildMemCommandLine(cmd, cfg, def, qemuCaps) < 0)
+ if (qemuBuildMemCommandLine(cmd, cfg, def, qemuCaps, priv) < 0)
goto error;
if (qemuBuildSmpCommandLine(cmd, def) < 0)
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 98d4ac90b5..656479ac45 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -129,6 +129,7 @@ int qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
virDomainDefPtr def,
virDomainMemoryDefPtr mem,
virBitmapPtr autoNodeset,
+ bool forbidPrealloc,
bool force);
char *qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ba3fff607a..0307acfe6a 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1944,6 +1944,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivatePtr priv)
VIR_FREE(priv->libDir);
VIR_FREE(priv->channelTargetDir);
+ priv->memPrealloc = false;
+
/* remove automatic pinning data */
virBitmapFree(priv->autoNodeset);
priv->autoNodeset = NULL;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 80bd4bde91..7ccbff8d26 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -370,6 +370,9 @@ struct _qemuDomainObjPrivate {
/* qemuProcessStartCPUs stores the reason for starting vCPUs here for the
* RESUME event handler to use it */
virDomainRunningReason runningReason;
+
+ /* true if global -mem-prealloc appears on cmd line */
+ bool memPrealloc;
};
# define QEMU_DOMAIN_PRIVATE(vm) \
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 0a63741b9e..6ead926f09 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2458,7 +2458,8 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
goto cleanup;
if (qemuBuildMemoryBackendProps(&props, objalias, cfg,
- priv->qemuCaps, vm->def, mem, NULL, true) <
0)
+ priv->qemuCaps, vm->def, mem, NULL,
+ priv->memPrealloc, true) < 0)
goto cleanup;
if (qemuProcessBuildDestroyMemoryPaths(driver, vm, mem, true) < 0)
diff --git a/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args
b/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args
index 143d8b041f..df90f7aad9 100644
--- a/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args
+++ b/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args
@@ -13,7 +13,7 @@ QEMU_AUDIO_DRV=none \
-mem-prealloc \
-mem-path /dev/hugepages2M/libvirt/qemu/-1-fedora \
-numa node,nodeid=0,cpus=0-1,mem=1024 \
--object memory-backend-file,id=memdimm0,prealloc=yes,\
+-object memory-backend-file,id=memdimm0,\
mem-path=/dev/hugepages1G/libvirt/qemu/-1-fedora,size=1073741824,\
host-nodes=1-3,policy=bind \
-device pc-dimm,node=0,memdev=memdimm0,id=dimm0,slot=0 \
--
2.18.1