From: Shivaprasad G Bhat <sb...@linux.vnet.ibm.com> With multifunction devices, multiple delete requests are sent to qemu and all the requests should be queued up.
Signed-off-by: Shivaprasad G Bhat <sb...@linux.vnet.ibm.com> Signed-off-by: Daniel Henrique Barboza <danielhb...@gmail.com> --- src/qemu/qemu_domain.h | 3 ++- src/qemu/qemu_hotplug.c | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 31c843de96..4fab1360f6 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -244,7 +244,8 @@ typedef enum { typedef struct _qemuDomainUnpluggingDevice qemuDomainUnpluggingDevice; typedef qemuDomainUnpluggingDevice *qemuDomainUnpluggingDevicePtr; struct _qemuDomainUnpluggingDevice { - const char *alias; + const char **aliases; + size_t naliases; qemuDomainUnpluggingDeviceStatus status; bool eventSeen; /* True if DEVICE_DELETED event arrived. */ }; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6991d7988c..b9946e8b8e 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -5134,13 +5134,19 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, static void qemuDomainMarkDeviceAliasForRemoval(virDomainObjPtr vm, - const char *alias) + const char *alias, + bool fresh) { qemuDomainObjPrivatePtr priv = vm->privateData; - memset(&priv->unplug, 0, sizeof(priv->unplug)); + if (fresh) + memset(&priv->unplug, 0, sizeof(priv->unplug)); + + if (VIR_REALLOC_N(priv->unplug.aliases, priv->unplug.naliases + 1) < 0) + return; + + priv->unplug.aliases[priv->unplug.naliases++] = alias; - priv->unplug.alias = alias; } @@ -5149,7 +5155,7 @@ qemuDomainMarkDeviceForRemoval(virDomainObjPtr vm, virDomainDeviceInfoPtr info) { - qemuDomainMarkDeviceAliasForRemoval(vm, info->alias); + qemuDomainMarkDeviceAliasForRemoval(vm, info->alias, true); } @@ -5157,7 +5163,9 @@ static void qemuDomainResetDeviceRemoval(virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; - priv->unplug.alias = NULL; + priv->unplug.aliases = NULL; + VIR_FREE(priv->unplug.aliases); + priv->unplug.naliases = 0; priv->unplug.eventSeen = false; } @@ -5192,13 +5200,14 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm) return 1; until += qemuDomainGetUnplugTimeout(vm); - while (priv->unplug.alias) { + /* All devices should get released around same time*/ + while (priv->unplug.naliases) { if ((rc = virDomainObjWaitUntil(vm, until)) == 1) return 0; if (rc < 0) { VIR_WARN("Failed to wait on unplug condition for domain '%s' " - "device '%s'", vm->def->name, priv->unplug.alias); + "device '%s'", vm->def->name, priv->unplug.aliases[0]); return 1; } } @@ -5224,14 +5233,16 @@ qemuDomainSignalDeviceRemoval(virDomainObjPtr vm, qemuDomainUnpluggingDeviceStatus status) { qemuDomainObjPrivatePtr priv = vm->privateData; + size_t i; - if (STREQ_NULLABLE(priv->unplug.alias, devAlias)) { - VIR_DEBUG("Removal of device '%s' continues in waiting thread", devAlias); - qemuDomainResetDeviceRemoval(vm); - priv->unplug.status = status; - priv->unplug.eventSeen = true; - virDomainObjBroadcast(vm); - return true; + for (i = 0; i < priv->unplug.naliases; i++) { + if (STREQ_NULLABLE(priv->unplug.aliases[i], devAlias)) { + VIR_DEBUG("Removal of device '%s' continues in waiting thread", devAlias); + VIR_DELETE_ELEMENT(priv->unplug.aliases, i, priv->unplug.naliases); + priv->unplug.status = status; + virDomainObjBroadcast(vm); + return true; + } } return false; } @@ -6075,7 +6086,7 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver, return -1; } - qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias); + qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias, true); if (qemuDomainDeleteDevice(vm, vcpupriv->alias) < 0) { if (virDomainObjIsActive(vm)) -- 2.26.2