There are a some scenarios in which we want to prealloc guest
memory (e.g. when requested in domain XML, when using hugepages,
etc.). With 'regular' <memory/> models (like 'dimm',
'nvdimm' or
'virtio-pmem') or regular guest memory it is corresponding
memory-backend-* object that ends up with .prealloc attribute
set. And that's desired because neither of those devices can
change its size on the fly. However, with virtio-mem model things
are a bit different. While one can set .prealloc attribute on
corresponding memory-backend-* object it doesn't make much sense,
because virtio-mem can inflate/deflate on the fly, i.e. change
how big of a portion of the memory-backend-* object is exposed to
the guest. For instance, from a say 4GiB module only a half can
be exposed to the guest. Therefore, it doesn't make much sense to
preallocate whole 4GiB and keep them allocated. But we still want
the part exposed to the guest preallocated (when conditions
described at the beginning are met).
Having said that, with new enough QEMU the virtio-mem-pci device
gained new attribute ".prealloc" which instructs the device to
talk to the memory backend object and allocate only the requested
portion of memory.
Now, that our algorithm for setting .prealloc was isolated in a
single function, the function can be called when constructing cmd
line for virtio-mem-pci device.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_command.c | 42 +++++++++++++------
src/qemu/qemu_command.h | 4 +-
src/qemu/qemu_hotplug.c | 2 +-
...mory-hotplug-virtio-mem.x86_64-latest.args | 2 +-
4 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9ab2b25fe2..c145f6242f 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3690,10 +3690,14 @@ qemuBuildMemoryGetPagesize(virQEMUDriverConfig *cfg,
if (useHugepage)
prealloc = true;
- *pagesizeRet = pagesize;
- *needHugepageRet = needHugepage;
- *useHugepageRet = useHugepage;
- *preallocRet = prealloc;
+ if (pagesizeRet)
+ *pagesizeRet = pagesize;
+ if (needHugepageRet)
+ *needHugepageRet = needHugepage;
+ if (useHugepageRet)
+ *useHugepageRet = useHugepage;
+ if (preallocRet)
+ *preallocRet = prealloc;
return 0;
}
@@ -3869,14 +3873,18 @@ qemuBuildMemoryBackendProps(virJSONValue **backendProps,
return -1;
if (mem->model == VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM) {
- /* Explicitly disable prealloc for virtio-mem as it's not supported
- * currently. Warn users if their config would result in prealloc. */
- if (priv->memPrealloc || prealloc) {
- VIR_WARN("Memory preallocation is unsupported for virtio-mem memory
devices");
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC))
{
+ /* Explicitly disable prealloc for virtio-mem if it isn't supported.
+ * Warn users if their config would result in prealloc. */
+ if (priv->memPrealloc || prealloc) {
+ VIR_WARN("Memory preallocation is unsupported for virtio-mem memory
devices");
+ }
+
+ if (priv->memPrealloc &&
+ virJSONValueObjectAppendBoolean(props, "prealloc", 0) < 0)
+ return -1;
}
- if (priv->memPrealloc &&
- virJSONValueObjectAppendBoolean(props, "prealloc", 0) < 0)
- return -1;
+
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MEMORY_BACKEND_RESERVE)
&&
virJSONValueObjectAppendBoolean(props, "reserve", 0) < 0)
return -1;
@@ -4029,7 +4037,9 @@ qemuBuildMemoryDimmBackendStr(virCommand *cmd,
virJSONValue *
-qemuBuildMemoryDeviceProps(const virDomainDef *def,
+qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,
+ qemuDomainObjPrivate *priv,
+ const virDomainDef *def,
const virDomainMemoryDef *mem)
{
g_autoptr(virJSONValue) props = NULL;
@@ -4037,6 +4047,7 @@ qemuBuildMemoryDeviceProps(const virDomainDef *def,
g_autofree char *uuidstr = NULL;
virTristateBool unarmed = VIR_TRISTATE_BOOL_ABSENT;
g_autofree char *memdev = NULL;
+ bool prealloc = false;
if (!mem->info.alias) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -4060,6 +4071,10 @@ qemuBuildMemoryDeviceProps(const virDomainDef *def,
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
device = "virtio-mem-pci";
+
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC)
&&
+ qemuBuildMemoryGetPagesize(cfg, def, mem, NULL, NULL, NULL, &prealloc)
< 0)
+ return NULL;
break;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
@@ -4087,6 +4102,7 @@ qemuBuildMemoryDeviceProps(const virDomainDef *def,
"S:uuid", uuidstr,
"T:unarmed", unarmed,
"s:memdev", memdev,
+ "B:prealloc", prealloc,
"s:id", mem->info.alias,
NULL) < 0)
return NULL;
@@ -7798,7 +7814,7 @@ qemuBuildMemoryDeviceCommandLine(virCommand *cmd,
if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv) < 0)
return -1;
- if (!(props = qemuBuildMemoryDeviceProps(def, def->mems[i])))
+ if (!(props = qemuBuildMemoryDeviceProps(cfg, priv, def, def->mems[i])))
return -1;
if (qemuBuildDeviceCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index dd981e333f..ba175aff9c 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -153,7 +153,9 @@ int qemuBuildMemoryBackendProps(virJSONValue **backendProps,
bool systemMemory);
virJSONValue *
-qemuBuildMemoryDeviceProps(const virDomainDef *def,
+qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,
+ qemuDomainObjPrivate *priv,
+ const virDomainDef *def,
const virDomainMemoryDef *mem);
/* Current, best practice */
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index f3ec24635d..efc6db8455 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2399,7 +2399,7 @@ qemuDomainAttachMemory(virQEMUDriver *driver,
objalias = g_strdup_printf("mem%s", mem->info.alias);
- if (!(devprops = qemuBuildMemoryDeviceProps(vm->def, mem)))
+ if (!(devprops = qemuBuildMemoryDeviceProps(cfg, priv, vm->def, mem)))
goto cleanup;
if (qemuBuildMemoryBackendProps(&props, objalias, cfg,
diff --git a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args
b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args
index 1d83ec88a8..77dbc0c89c 100644
--- a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args
+++ b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args
@@ -21,7 +21,7 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
-object
'{"qom-type":"memory-backend-ram","id":"memvirtiomem0","reserve":false,"size":1073741824}'
\
-device
'{"driver":"virtio-mem-pci","node":0,"block-size":2097152,"requested-size":536870912,"memdev":"memvirtiomem0","id":"virtiomem0","bus":"pci.0","addr":"0x2"}'
\
-object
'{"qom-type":"memory-backend-file","id":"memvirtiomem1","mem-path":"/dev/hugepages2M/libvirt/qemu/-1-QEMUGuest1","reserve":false,"size":2147483648,"host-nodes":[1,2,3],"policy":"bind"}'
\
--device
'{"driver":"virtio-mem-pci","node":0,"block-size":2097152,"requested-size":1073741824,"memdev":"memvirtiomem1","id":"virtiomem1","bus":"pci.0","addr":"0x3"}'
\
+-device
'{"driver":"virtio-mem-pci","node":0,"block-size":2097152,"requested-size":1073741824,"memdev":"memvirtiomem1","prealloc":true,"id":"virtiomem1","bus":"pci.0","addr":"0x3"}'
\
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
-display none \
-no-user-config \
--
2.34.1