Re: [libvirt] [PATCHv3 11/12] qemu: Implement memory device hotplug
On Thu, Mar 19, 2015 at 18:40:36 -0400, John Ferlan wrote: On 03/17/2015 10:20 AM, Peter Krempa wrote: Add code to hot-add memory devices to running qemu instances. --- Notes: Version 3: - added comment to clarify that @mem is always consumed by qemuDomainAttachMemory Version 2: - no change Version 2: - no change src/qemu/qemu_command.c | 4 +-- src/qemu/qemu_command.h | 15 src/qemu/qemu_driver.c | 5 ++- src/qemu/qemu_hotplug.c | 95 + src/qemu/qemu_hotplug.h | 3 ++ 5 files changed, 119 insertions(+), 3 deletions(-) @@ -1672,6 +1672,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) Coverity determines that qemuBuildMemoryBackendStr can return props here with a -1 return and thus leak props That's because qemuBuildMemoryBackendStr sets the returned *backendProps and sets the local props to NULL before the (!hugepages) code which if it fails won't cause 'props' to be free'd properly Adding the virJSONValueFree(props); makes Coverity happy again. I'll fix qemuBuildMemoryBackendStr separately rather than adding a pseudo-hack that would violate the style we are using for functions that return via argument. Peter signature.asc Description: Digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCHv3 11/12] qemu: Implement memory device hotplug
On 03/17/2015 10:20 AM, Peter Krempa wrote: Add code to hot-add memory devices to running qemu instances. --- Notes: Version 3: - added comment to clarify that @mem is always consumed by qemuDomainAttachMemory Version 2: - no change Version 2: - no change src/qemu/qemu_command.c | 4 +-- src/qemu/qemu_command.h | 15 src/qemu/qemu_driver.c | 5 ++- src/qemu/qemu_hotplug.c | 95 + src/qemu/qemu_hotplug.h | 3 ++ 5 files changed, 119 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2d85567..1f72437 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -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, @@ -4872,7 +4872,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 e948cca..cbdf279 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7649,8 +7649,11 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, dev-data.rng = NULL; break; -/*TODO: implement later */ case VIR_DOMAIN_DEVICE_MEMORY: +ret = qemuDomainAttachMemory(driver, vm, + dev-data.memory); +dev-data.memory = NULL; +break; FWIW: Although there is a note in the AttachMemory code about consumption it may be worth noting here too just so no one in the future sees it missing and adds it thinking it's necessary 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 5c5ad0e..88c5e3c 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1672,6 +1672,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) Coverity determines that qemuBuildMemoryBackendStr can return props here with a -1 return and thus leak
[libvirt] [PATCHv3 11/12] qemu: Implement memory device hotplug
Add code to hot-add memory devices to running qemu instances. --- Notes: Version 3: - added comment to clarify that @mem is always consumed by qemuDomainAttachMemory Version 2: - no change Version 2: - no change src/qemu/qemu_command.c | 4 +-- src/qemu/qemu_command.h | 15 src/qemu/qemu_driver.c | 5 ++- src/qemu/qemu_hotplug.c | 95 + src/qemu/qemu_hotplug.h | 3 ++ 5 files changed, 119 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2d85567..1f72437 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -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, @@ -4872,7 +4872,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 e948cca..cbdf279 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7649,8 +7649,11 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, dev-data.rng = NULL; break; -/*TODO: implement later */ case VIR_DOMAIN_DEVICE_MEMORY: +ret = qemuDomainAttachMemory(driver, vm, + dev-data.memory); +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 5c5ad0e..88c5e3c 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1672,6 +1672,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)); +