qemu: Allow prealloc for virtio-mem-pci

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@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Michal Privoznik 2021-11-30 18:16:00 +01:00
parent a82d9e8996
commit f9db6f3ab6
4 changed files with 34 additions and 16 deletions

View File

@ -3692,10 +3692,14 @@ qemuBuildMemoryGetPagesize(virQEMUDriverConfig *cfg,
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;
}
@ -3871,14 +3875,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;
@ -4031,7 +4039,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;
@ -4039,6 +4049,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",
@ -4062,6 +4073,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:
@ -4089,6 +4104,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;
@ -7792,7 +7808,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)

View File

@ -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 */

View File

@ -2400,7 +2400,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,

View File

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