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

Reply via email to