mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
qemu: Implement memory device hotplug
Add code to hot-add memory devices to running qemu instances.
This commit is contained in:
parent
96094fb28d
commit
9b4654f6f1
@ -4599,7 +4599,7 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
|
||||
* other configuration was used (to detect legacy configurations). Returns
|
||||
* -1 in case of an error.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
qemuBuildMemoryBackendStr(unsigned long long size,
|
||||
unsigned long long pagesize,
|
||||
int guestNode,
|
||||
@ -4873,7 +4873,7 @@ qemuBuildMemoryDimmBackendStr(virDomainMemoryDefPtr mem,
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
char *
|
||||
qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
|
||||
virQEMUCapsPtr qemuCaps)
|
||||
{
|
||||
|
@ -162,6 +162,21 @@ char *qemuBuildSoundDevStr(virDomainDefPtr domainDef,
|
||||
virDomainSoundDefPtr sound,
|
||||
virQEMUCapsPtr qemuCaps);
|
||||
|
||||
int qemuBuildMemoryBackendStr(unsigned long long size,
|
||||
unsigned long long pagesize,
|
||||
int guestNode,
|
||||
virBitmapPtr userNodeset,
|
||||
virBitmapPtr autoNodeset,
|
||||
virDomainDefPtr def,
|
||||
virQEMUCapsPtr qemuCaps,
|
||||
virQEMUDriverConfigPtr cfg,
|
||||
const char **backendType,
|
||||
virJSONValuePtr *backendProps,
|
||||
bool force);
|
||||
|
||||
char *qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
|
||||
virQEMUCapsPtr qemuCaps);
|
||||
|
||||
/* Legacy, pre device support */
|
||||
char *qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev,
|
||||
virQEMUCapsPtr qemuCaps);
|
||||
|
@ -7656,8 +7656,12 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
|
||||
dev->data.rng = NULL;
|
||||
break;
|
||||
|
||||
/*TODO: implement later */
|
||||
case VIR_DOMAIN_DEVICE_MEMORY:
|
||||
/* note that qemuDomainAttachMemory always consumes dev->data.memory */
|
||||
ret = qemuDomainAttachMemory(driver, vm,
|
||||
dev->data.memory);
|
||||
dev->data.memory = NULL;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DEVICE_NONE:
|
||||
case VIR_DOMAIN_DEVICE_FS:
|
||||
|
@ -1680,6 +1680,101 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qemuDomainAttachMemory:
|
||||
* @driver: qemu driver data
|
||||
* @vm: VM object
|
||||
* @mem: Definition of the memory device to be attached. @mem is always consumed
|
||||
*
|
||||
* Attaches memory device described by @mem to domain @vm.
|
||||
*
|
||||
* Returns 0 on success -1 on error.
|
||||
*/
|
||||
int
|
||||
qemuDomainAttachMemory(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainMemoryDefPtr mem)
|
||||
{
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||
char *devstr = NULL;
|
||||
char *objalias = NULL;
|
||||
const char *backendType;
|
||||
virJSONValuePtr props = NULL;
|
||||
int id;
|
||||
int ret = -1;
|
||||
|
||||
if (virAsprintf(&mem->info.alias, "dimm%zu", vm->def->nmems) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virAsprintf(&objalias, "mem%s", mem->info.alias) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!(devstr = qemuBuildMemoryDeviceStr(mem, priv->qemuCaps)))
|
||||
goto cleanup;
|
||||
|
||||
qemuDomainMemoryDeviceAlignSize(mem);
|
||||
|
||||
if (qemuBuildMemoryBackendStr(mem->size, mem->pagesize,
|
||||
mem->targetNode, mem->sourceNodes, NULL,
|
||||
vm->def, priv->qemuCaps, cfg,
|
||||
&backendType, &props, true) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virDomainMemoryInsert(vm->def, mem) < 0) {
|
||||
virJSONValueFree(props);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
if (qemuMonitorAddObject(priv->mon, backendType, objalias, props) < 0)
|
||||
goto removedef;
|
||||
|
||||
if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
|
||||
virErrorPtr err = virSaveLastError();
|
||||
ignore_value(qemuMonitorDelObject(priv->mon, objalias));
|
||||
virSetError(err);
|
||||
virFreeError(err);
|
||||
goto removedef;
|
||||
}
|
||||
|
||||
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
||||
/* we shouldn't touch mem now, as the def might be freed */
|
||||
mem = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* mem is consumed by vm->def */
|
||||
mem = NULL;
|
||||
|
||||
/* this step is best effort, removing the device would be so much trouble */
|
||||
ignore_value(qemuDomainUpdateMemoryDeviceInfo(driver, vm,
|
||||
QEMU_ASYNC_JOB_NONE));
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virObjectUnref(cfg);
|
||||
VIR_FREE(devstr);
|
||||
VIR_FREE(objalias);
|
||||
virDomainMemoryDefFree(mem);
|
||||
return ret;
|
||||
|
||||
removedef:
|
||||
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
||||
mem = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((id = virDomainMemoryFindByDef(vm->def, mem)) >= 0)
|
||||
mem = virDomainMemoryRemove(vm->def, id);
|
||||
else
|
||||
mem = NULL;
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
|
@ -57,6 +57,9 @@ int qemuDomainAttachHostDevice(virConnectPtr conn,
|
||||
virDomainHostdevDefPtr hostdev);
|
||||
int qemuDomainFindGraphicsIndex(virDomainDefPtr def,
|
||||
virDomainGraphicsDefPtr dev);
|
||||
int qemuDomainAttachMemory(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainMemoryDefPtr mem);
|
||||
int qemuDomainChangeGraphics(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainGraphicsDefPtr dev);
|
||||
|
Loading…
x
Reference in New Issue
Block a user