[libvirt] [RFC PATCH 23/28] qemu: hotplug: Queue and wait for multiple devices

Shivaprasad G Bhat posted 28 patches 6 years, 8 months ago
[libvirt] [RFC PATCH 23/28] qemu: hotplug: Queue and wait for multiple devices
Posted by Shivaprasad G Bhat 6 years, 8 months ago
With multifunction devices, multiple delete requests are sent
to qemu and all the requests should be queued up.

Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
---
 src/qemu/qemu_domain.h  |    3 ++-
 src/qemu/qemu_hotplug.c |   38 ++++++++++++++++++++++++--------------
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 339d0ba82c..85cbc2b5e8 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -195,7 +195,8 @@ typedef enum {
 typedef struct _qemuDomainUnpluggingDevice qemuDomainUnpluggingDevice;
 typedef qemuDomainUnpluggingDevice *qemuDomainUnpluggingDevicePtr;
 struct _qemuDomainUnpluggingDevice {
-    const char *alias;
+    const char **aliases;
+    size_t naliases;
     qemuDomainUnpluggingDeviceStatus status;
 };
 
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 007ecb0923..7dffaf9502 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4542,16 +4542,21 @@ 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 (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
         return;
 
-    priv->unplug.alias = alias;
+    if (VIR_REALLOC_N(priv->unplug.aliases, priv->unplug.naliases + 1) < 0)
+        return;
+
+    priv->unplug.aliases[priv->unplug.naliases++] = alias;
 }
 
 
@@ -4560,7 +4565,7 @@ qemuDomainMarkDeviceForRemoval(virDomainObjPtr vm,
                                virDomainDeviceInfoPtr info)
 
 {
-    qemuDomainMarkDeviceAliasForRemoval(vm, info->alias);
+    qemuDomainMarkDeviceAliasForRemoval(vm, info->alias, true);
 }
 
 
@@ -4568,7 +4573,8 @@ static void
 qemuDomainResetDeviceRemoval(virDomainObjPtr vm)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    priv->unplug.alias = NULL;
+    VIR_FREE(priv->unplug.aliases);
+    priv->unplug.naliases = 0;
 }
 
 /* Returns:
@@ -4596,13 +4602,14 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
         return 1;
     until += qemuDomainRemoveDeviceWaitTime;
 
-    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;
         }
     }
@@ -4627,14 +4634,17 @@ qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
                               const char *devAlias,
                               qemuDomainUnpluggingDeviceStatus status)
 {
+    size_t i;
     qemuDomainObjPrivatePtr priv = vm->privateData;
 
-    if (STREQ_NULLABLE(priv->unplug.alias, devAlias)) {
-        VIR_DEBUG("Removal of device '%s' continues in waiting thread", devAlias);
-        qemuDomainResetDeviceRemoval(vm);
-        priv->unplug.status = status;
-        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;
 }
@@ -5675,7 +5685,7 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
+    qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias, true);
 
     qemuDomainObjEnterMonitor(driver, vm);
 

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list