qemu: hotplug: Fix mlock limit handling on memory hotplug

If mlock is required either due to use of VFIO hostdevs or due to the
fact that it's enabled it needs to be tweaked prior to adding new memory
or after removing a module. Add a helper to determine when it's
necessary and reuse it both on hotplug and hotunplug.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1273491
This commit is contained in:
Peter Krempa 2015-11-06 16:39:31 +01:00
parent fbc58cfcae
commit ec90b34acf
3 changed files with 58 additions and 3 deletions

View File

@ -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;
}

View File

@ -483,5 +483,6 @@ int qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
virDomainObjPtr vm);
unsigned long long qemuDomainGetMlockLimitBytes(virDomainDefPtr def);
bool qemuDomainRequiresMlock(virDomainDefPtr def);
#endif /* __QEMU_DOMAIN_H__ */

View File

@ -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;
}