提交 9b4654f6 编写于 作者: P Peter Krempa

qemu: Implement memory device hotplug

Add code to hot-add memory devices to running qemu instances.
上级 96094fb2
...@@ -4599,7 +4599,7 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, ...@@ -4599,7 +4599,7 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
* other configuration was used (to detect legacy configurations). Returns * other configuration was used (to detect legacy configurations). Returns
* -1 in case of an error. * -1 in case of an error.
*/ */
static int int
qemuBuildMemoryBackendStr(unsigned long long size, qemuBuildMemoryBackendStr(unsigned long long size,
unsigned long long pagesize, unsigned long long pagesize,
int guestNode, int guestNode,
...@@ -4873,7 +4873,7 @@ qemuBuildMemoryDimmBackendStr(virDomainMemoryDefPtr mem, ...@@ -4873,7 +4873,7 @@ qemuBuildMemoryDimmBackendStr(virDomainMemoryDefPtr mem,
} }
static char * char *
qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem, qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
virQEMUCapsPtr qemuCaps) virQEMUCapsPtr qemuCaps)
{ {
......
...@@ -162,6 +162,21 @@ char *qemuBuildSoundDevStr(virDomainDefPtr domainDef, ...@@ -162,6 +162,21 @@ char *qemuBuildSoundDevStr(virDomainDefPtr domainDef,
virDomainSoundDefPtr sound, virDomainSoundDefPtr sound,
virQEMUCapsPtr qemuCaps); 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 */ /* Legacy, pre device support */
char *qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev, char *qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev,
virQEMUCapsPtr qemuCaps); virQEMUCapsPtr qemuCaps);
......
...@@ -7656,8 +7656,12 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, ...@@ -7656,8 +7656,12 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
dev->data.rng = NULL; dev->data.rng = NULL;
break; break;
/*TODO: implement later */
case VIR_DOMAIN_DEVICE_MEMORY: 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_NONE:
case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_FS:
......
...@@ -1680,6 +1680,101 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, ...@@ -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 static int
qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver, qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
......
...@@ -57,6 +57,9 @@ int qemuDomainAttachHostDevice(virConnectPtr conn, ...@@ -57,6 +57,9 @@ int qemuDomainAttachHostDevice(virConnectPtr conn,
virDomainHostdevDefPtr hostdev); virDomainHostdevDefPtr hostdev);
int qemuDomainFindGraphicsIndex(virDomainDefPtr def, int qemuDomainFindGraphicsIndex(virDomainDefPtr def,
virDomainGraphicsDefPtr dev); virDomainGraphicsDefPtr dev);
int qemuDomainAttachMemory(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainMemoryDefPtr mem);
int qemuDomainChangeGraphics(virQEMUDriverPtr driver, int qemuDomainChangeGraphics(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
virDomainGraphicsDefPtr dev); virDomainGraphicsDefPtr dev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册