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@xxxxxxxxxx> --- 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