diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index f016e8b3f6..416ab5b5df 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3643,3 +3643,30 @@ qemuDomainGetMlockLimitBytes(virDomainDefPtr def) return memKB << 10; } + + +/** + * @def: domain definition + * + * Returns ture if the locked memory limit needs to be set or updated due to + * configuration or passthrough devices. + * */ +bool +qemuDomainRequiresMlock(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; + } + + return false; +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index e34370b08b..4be998c27d 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -483,5 +483,6 @@ int qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver, virDomainObjPtr vm); unsigned long long qemuDomainGetMlockLimitBytes(virDomainDefPtr def); +bool qemuDomainRequiresMlock(virDomainDefPtr def); #endif /* __QEMU_DOMAIN_H__ */ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index e7fc036471..b02e9050f2 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1768,6 +1768,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver, virJSONValuePtr props = NULL; virObjectEventPtr event; bool fix_balloon = false; + bool mlock = false; int id; int ret = -1; @@ -1802,16 +1803,26 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver, goto cleanup; } + mlock = qemuDomainRequiresMlock(vm->def); + + if (mlock && + virProcessSetMaxMemLock(vm->pid, + qemuDomainGetMlockLimitBytes(vm->def)) < 0) { + mlock = false; + virJSONValueFree(props); + goto removedef; + } + qemuDomainObjEnterMonitor(driver, vm); if (qemuMonitorAddObject(priv->mon, backendType, objalias, props) < 0) - goto removedef; + goto exit_monitor; if (qemuMonitorAddDevice(priv->mon, devstr) < 0) { virErrorPtr err = virSaveLastError(); ignore_value(qemuMonitorDelObject(priv->mon, objalias)); virSetError(err); virFreeError(err); - goto removedef; + goto exit_monitor; } if (qemuDomainObjExitMonitor(driver, vm) < 0) { @@ -1845,17 +1856,27 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver, virDomainMemoryDefFree(mem); return ret; - removedef: + exit_monitor: if (qemuDomainObjExitMonitor(driver, vm) < 0) { mem = NULL; goto audit; } + removedef: if ((id = virDomainMemoryFindByDef(vm->def, mem)) >= 0) mem = virDomainMemoryRemove(vm->def, id); else mem = NULL; + /* reset the mlock limit */ + if (mlock) { + virErrorPtr err = virSaveLastError(); + ignore_value(virProcessSetMaxMemLock(vm->pid, + qemuDomainGetMlockLimitBytes(vm->def))); + virSetError(err); + virFreeError(err); + } + goto audit; } @@ -2947,6 +2968,12 @@ qemuDomainRemoveMemoryDevice(virQEMUDriverPtr driver, virDomainMemoryRemove(vm->def, idx); virDomainMemoryDefFree(mem); + + /* decrease the mlock limit after memory unplug if necessary */ + if (qemuDomainRequiresMlock(vm->def)) + ignore_value(virProcessSetMaxMemLock(vm->pid, + qemuDomainGetMlockLimitBytes(vm->def))); + return 0; }