[libvirt] [PATCHv2.5 09/10] qemu: Implement memory device hotplug
John Ferlan
jferlan at redhat.com
Sat Mar 14 00:48:39 UTC 2015
On 03/04/2015 11:25 AM, Peter Krempa wrote:
> Add code to hot-add memory devices to running qemu instances.
> ---
> src/qemu/qemu_command.c | 4 +--
> src/qemu/qemu_command.h | 15 +++++++++
> src/qemu/qemu_driver.c | 5 ++-
> src/qemu/qemu_hotplug.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_hotplug.h | 3 ++
> 5 files changed, 109 insertions(+), 3 deletions(-)
>
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index f1fca02..883c3d1 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -4546,7 +4546,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,
> @@ -4819,7 +4819,7 @@ qemuBuildMemoryDimmBackendStr(virDomainMemoryDefPtr mem,
> }
>
>
> -static char *
> +char *
> qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
> virQEMUCapsPtr qemuCaps)
> {
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index ee81f92..a29db41 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -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);
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 6b10e96..b917d76 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -7095,8 +7095,11 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
> dev->data.rng = NULL;
> break;
>
> - /*TODO: implement later */
> case VIR_DOMAIN_DEVICE_MEMORY:
> + ret = qemuDomainAttachMemory(driver, vm,
> + dev->data.memory);
Shouldn't there be a :
if (!ret)
prior to the following line (like the other cases in the switch)
> + dev->data.memory = NULL;
> + break;
>
> case VIR_DOMAIN_DEVICE_NONE:
> case VIR_DOMAIN_DEVICE_FS:
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index cb2270e..967b678 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -1672,6 +1672,91 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
> }
>
>
> +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)
I see from the AddObject comments, props is consumed upon success, but
if we hit the else of mon->json, then we don't free it which we should -
not related to this particular code, but something that should be fixed...
> + 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;
Since both the Exit error path and this path set mem = NULL, why not
just set it before the Exit and comment that it'll either consumed by
vm->def on success or might be freed on failure...
> +
> + /* this step is best effort, removing the device would be so much trouble */
> + ignore_value(qemuDomainUpdateMemoryDeviceInfo(driver, vm,
> + QEMU_ASYNC_JOB_NONE));
> +
BTW: This is perhaps what I was thinking of in that migration path patch
(#6) where the code fails if not defined.
ACK - with the slight adjustment above for the first thing I noted.
John
> + 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,
> diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
> index 8a0b313..ad4ff38 100644
> --- a/src/qemu/qemu_hotplug.h
> +++ b/src/qemu/qemu_hotplug.h
> @@ -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);
>
More information about the libvir-list
mailing list