[libvirt] [PATCH v2 10/12] qemu_hotplug: Allow asynchronous detach

Michal Privoznik posted 12 patches 6 years, 11 months ago
[libvirt] [PATCH v2 10/12] qemu_hotplug: Allow asynchronous detach
Posted by Michal Privoznik 6 years, 11 months ago
The virDomainDetachDeviceAlias API is designed so that it only
sends detach request to qemu. It's user's responsibility to wait
for DEVICE_DELETED event, not libvirt's. Add @async flag to
qemuDomainDetach*Device() functions so that caller can chose if
detach is semi-synchronous (old virDomainDetachDeviceFlags()) or
fully asynchronous (new virDomainDetachDeviceFlags()).

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 src/qemu/qemu_driver.c  |  32 +++----
 src/qemu/qemu_hotplug.c | 231 ++++++++++++++++++++++++++++++++----------------
 src/qemu/qemu_hotplug.h |  33 ++++---
 tests/qemuhotplugtest.c |  13 +--
 4 files changed, 203 insertions(+), 106 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2347e71cfb..81a9833b39 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7726,14 +7726,15 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
 static int
 qemuDomainDetachDeviceControllerLive(virQEMUDriverPtr driver,
                                      virDomainObjPtr vm,
-                                     virDomainDeviceDefPtr dev)
+                                     virDomainDeviceDefPtr dev,
+                                     bool async)
 {
     virDomainControllerDefPtr cont = dev->data.controller;
     int ret = -1;
 
     switch (cont->type) {
     case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
-        ret = qemuDomainDetachControllerDevice(driver, vm, dev);
+        ret = qemuDomainDetachControllerDevice(driver, vm, dev, async);
         break;
     default :
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
@@ -7746,46 +7747,47 @@ qemuDomainDetachDeviceControllerLive(virQEMUDriverPtr driver,
 static int
 qemuDomainDetachDeviceLive(virDomainObjPtr vm,
                            virDomainDeviceDefPtr dev,
-                           virQEMUDriverPtr driver)
+                           virQEMUDriverPtr driver,
+                           bool async)
 {
     int ret = -1;
 
     switch ((virDomainDeviceType)dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
-        ret = qemuDomainDetachDeviceDiskLive(driver, vm, dev);
+        ret = qemuDomainDetachDeviceDiskLive(driver, vm, dev, async);
         break;
     case VIR_DOMAIN_DEVICE_CONTROLLER:
-        ret = qemuDomainDetachDeviceControllerLive(driver, vm, dev);
+        ret = qemuDomainDetachDeviceControllerLive(driver, vm, dev, async);
         break;
     case VIR_DOMAIN_DEVICE_LEASE:
         ret = qemuDomainDetachLease(driver, vm, dev->data.lease);
         break;
     case VIR_DOMAIN_DEVICE_NET:
-        ret = qemuDomainDetachNetDevice(driver, vm, dev);
+        ret = qemuDomainDetachNetDevice(driver, vm, dev, async);
         break;
     case VIR_DOMAIN_DEVICE_HOSTDEV:
-        ret = qemuDomainDetachHostDevice(driver, vm, dev);
+        ret = qemuDomainDetachHostDevice(driver, vm, dev, async);
         break;
     case VIR_DOMAIN_DEVICE_CHR:
-        ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr);
+        ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr, async);
         break;
     case VIR_DOMAIN_DEVICE_RNG:
-        ret = qemuDomainDetachRNGDevice(driver, vm, dev->data.rng);
+        ret = qemuDomainDetachRNGDevice(driver, vm, dev->data.rng, async);
         break;
     case VIR_DOMAIN_DEVICE_MEMORY:
-        ret = qemuDomainDetachMemoryDevice(driver, vm, dev->data.memory);
+        ret = qemuDomainDetachMemoryDevice(driver, vm, dev->data.memory, async);
         break;
     case VIR_DOMAIN_DEVICE_SHMEM:
-        ret = qemuDomainDetachShmemDevice(driver, vm, dev->data.shmem);
+        ret = qemuDomainDetachShmemDevice(driver, vm, dev->data.shmem, async);
         break;
     case VIR_DOMAIN_DEVICE_WATCHDOG:
-        ret = qemuDomainDetachWatchdog(driver, vm, dev->data.watchdog);
+        ret = qemuDomainDetachWatchdog(driver, vm, dev->data.watchdog, async);
         break;
     case VIR_DOMAIN_DEVICE_INPUT:
-        ret = qemuDomainDetachInputDevice(vm, dev->data.input);
+        ret = qemuDomainDetachInputDevice(vm, dev->data.input, async);
         break;
     case VIR_DOMAIN_DEVICE_REDIRDEV:
-        ret = qemuDomainDetachRedirdevDevice(driver, vm, dev->data.redirdev);
+        ret = qemuDomainDetachRedirdevDevice(driver, vm, dev->data.redirdev, async);
         break;
 
     case VIR_DOMAIN_DEVICE_FS:
@@ -8716,7 +8718,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver,
     }
 
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (qemuDomainDetachDeviceLive(vm, dev_copy, driver) < 0)
+        if (qemuDomainDetachDeviceLive(vm, dev_copy, driver, false) < 0)
             goto cleanup;
         /*
          * update domain status forcibly because the domain status may be
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e84dc909b9..5b5c27b011 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4740,7 +4740,8 @@ qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
 static int
 qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
                                  virDomainObjPtr vm,
-                                 virDomainDiskDefPtr detach)
+                                 virDomainDiskDefPtr detach,
+                                 bool async)
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -4757,7 +4758,8 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
@@ -4769,18 +4771,24 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
 
 static int
 qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
                            virDomainObjPtr vm,
-                           virDomainDiskDefPtr detach)
+                           virDomainDiskDefPtr detach,
+                           bool async)
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -4788,7 +4796,8 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
     if (qemuDomainDiskBlockJobIsActive(detach))
         goto cleanup;
 
-    qemuDomainMarkDeviceForRemoval(vm, &detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
@@ -4800,11 +4809,16 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
 
@@ -4824,7 +4838,8 @@ qemuFindDisk(virDomainDefPtr def, const char *dst)
 int
 qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-                               virDomainDeviceDefPtr dev)
+                               virDomainDeviceDefPtr dev,
+                               bool async)
 {
     virDomainDiskDefPtr disk;
     int ret = -1;
@@ -4841,10 +4856,10 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
     case VIR_DOMAIN_DISK_DEVICE_DISK:
     case VIR_DOMAIN_DISK_DEVICE_LUN:
         if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)
-            ret = qemuDomainDetachVirtioDiskDevice(driver, vm, disk);
+            ret = qemuDomainDetachVirtioDiskDevice(driver, vm, disk, async);
         else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
                  disk->bus == VIR_DOMAIN_DISK_BUS_USB)
-            ret = qemuDomainDetachDiskDevice(driver, vm, disk);
+            ret = qemuDomainDetachDiskDevice(driver, vm, disk, async);
         else
             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                            _("This type of disk cannot be hot unplugged"));
@@ -4922,7 +4937,8 @@ static bool qemuDomainControllerIsBusy(virDomainObjPtr vm,
 
 int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
                                      virDomainObjPtr vm,
-                                     virDomainDeviceDefPtr dev)
+                                     virDomainDeviceDefPtr dev,
+                                     bool async)
 {
     int idx, ret = -1;
     virDomainControllerDefPtr detach = NULL;
@@ -4974,7 +4990,8 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
@@ -4984,18 +5001,24 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveControllerDevice(driver, vm, detach);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveControllerDevice(driver, vm, detach);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
 
 static int
 qemuDomainDetachHostPCIDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
-                              virDomainHostdevDefPtr detach)
+                              virDomainHostdevDefPtr detach,
+                              bool async)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainHostdevSubsysPCIPtr pcisrc = &detach->source.subsys.u.pci;
@@ -5009,7 +5032,8 @@ qemuDomainDetachHostPCIDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
@@ -5022,7 +5046,8 @@ qemuDomainDetachHostPCIDevice(virQEMUDriverPtr driver,
 static int
 qemuDomainDetachHostUSBDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
-                              virDomainHostdevDefPtr detach)
+                              virDomainHostdevDefPtr detach,
+                              bool async)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret;
@@ -5033,7 +5058,8 @@ qemuDomainDetachHostUSBDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
@@ -5046,7 +5072,8 @@ qemuDomainDetachHostUSBDevice(virQEMUDriverPtr driver,
 static int
 qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-                               virDomainHostdevDefPtr detach)
+                               virDomainHostdevDefPtr detach,
+                               bool async)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
@@ -5057,7 +5084,8 @@ qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
@@ -5071,7 +5099,8 @@ qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver,
 static int
 qemuDomainDetachSCSIVHostDevice(virQEMUDriverPtr driver,
                                 virDomainObjPtr vm,
-                                virDomainHostdevDefPtr detach)
+                                virDomainHostdevDefPtr detach,
+                                bool async)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
@@ -5082,7 +5111,8 @@ qemuDomainDetachSCSIVHostDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
@@ -5097,7 +5127,8 @@ qemuDomainDetachSCSIVHostDevice(virQEMUDriverPtr driver,
 static int
 qemuDomainDetachMediatedDevice(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-                               virDomainHostdevDefPtr detach)
+                               virDomainHostdevDefPtr detach,
+                               bool async)
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -5108,7 +5139,8 @@ qemuDomainDetachMediatedDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
@@ -5122,7 +5154,8 @@ qemuDomainDetachMediatedDevice(virQEMUDriverPtr driver,
 static int
 qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-                               virDomainHostdevDefPtr detach)
+                               virDomainHostdevDefPtr detach,
+                               bool async)
 {
     int ret = -1;
 
@@ -5131,19 +5164,19 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
 
     switch (detach->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
-        ret = qemuDomainDetachHostPCIDevice(driver, vm, detach);
+        ret = qemuDomainDetachHostPCIDevice(driver, vm, detach, async);
         break;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
-        ret = qemuDomainDetachHostUSBDevice(driver, vm, detach);
+        ret = qemuDomainDetachHostUSBDevice(driver, vm, detach, async);
         break;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
-        ret = qemuDomainDetachHostSCSIDevice(driver, vm, detach);
+        ret = qemuDomainDetachHostSCSIDevice(driver, vm, detach, async);
         break;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
-        ret = qemuDomainDetachSCSIVHostDevice(driver, vm, detach);
+        ret = qemuDomainDetachSCSIVHostDevice(driver, vm, detach, async);
         break;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
-        ret = qemuDomainDetachMediatedDevice(driver, vm, detach);
+        ret = qemuDomainDetachMediatedDevice(driver, vm, detach, async);
         break;
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -5155,11 +5188,13 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
     if (ret < 0) {
         if (virDomainObjIsActive(vm))
             virDomainAuditHostdev(vm, detach, "detach", false);
-    } else if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1) {
+    } else if (!async &&
+               (ret = qemuDomainWaitForDeviceRemoval(vm)) == 1) {
         ret = qemuDomainRemoveHostDevice(driver, vm, detach);
     }
 
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
 
     return ret;
 }
@@ -5167,7 +5202,8 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
 /* search for a hostdev matching dev and detach it */
 int qemuDomainDetachHostDevice(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-                               virDomainDeviceDefPtr dev)
+                               virDomainDeviceDefPtr dev,
+                               bool async)
 {
     virDomainHostdevDefPtr hostdev = dev->data.hostdev;
     virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
@@ -5242,16 +5278,17 @@ int qemuDomainDetachHostDevice(virQEMUDriverPtr driver,
      * function so that mac address / virtualport are reset
      */
     if (detach->parent.type == VIR_DOMAIN_DEVICE_NET)
-        return qemuDomainDetachNetDevice(driver, vm, &detach->parent);
+        return qemuDomainDetachNetDevice(driver, vm, &detach->parent, async);
     else
-        return qemuDomainDetachThisHostDevice(driver, vm, detach);
+        return qemuDomainDetachThisHostDevice(driver, vm, detach, async);
 }
 
 
 int
 qemuDomainDetachShmemDevice(virQEMUDriverPtr driver,
                             virDomainObjPtr vm,
-                            virDomainShmemDefPtr dev)
+                            virDomainShmemDefPtr dev,
+                            bool async)
 {
     int ret = -1;
     ssize_t idx = -1;
@@ -5282,7 +5319,8 @@ qemuDomainDetachShmemDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &shmem->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &shmem->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, shmem->info.alias) < 0) {
@@ -5304,7 +5342,8 @@ qemuDomainDetachShmemDevice(virQEMUDriverPtr driver,
 int
 qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
                          virDomainObjPtr vm,
-                         virDomainWatchdogDefPtr dev)
+                         virDomainWatchdogDefPtr dev,
+                         bool async)
 {
     int ret = -1;
     virDomainWatchdogDefPtr watchdog = vm->def->watchdog;
@@ -5336,7 +5375,8 @@ qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &watchdog->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &watchdog->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, watchdog->info.alias) < 0) {
@@ -5358,7 +5398,8 @@ qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
 int
 qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-                               virDomainRedirdevDefPtr dev)
+                               virDomainRedirdevDefPtr dev,
+                               bool async)
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -5379,7 +5420,8 @@ qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &tmpRedirdevDef->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &tmpRedirdevDef->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, tmpRedirdevDef->info.alias) < 0) {
@@ -5389,11 +5431,16 @@ qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveRedirdevDevice(driver, vm, tmpRedirdevDef);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveRedirdevDevice(driver, vm, tmpRedirdevDef);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
 
@@ -5401,7 +5448,8 @@ qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
 int
 qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
                           virDomainObjPtr vm,
-                          virDomainDeviceDefPtr dev)
+                          virDomainDeviceDefPtr dev,
+                          bool async)
 {
     int detachidx, ret = -1;
     virDomainNetDefPtr detach = NULL;
@@ -5414,7 +5462,8 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
 
     if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
         ret = qemuDomainDetachThisHostDevice(driver, vm,
-                                             virDomainNetGetActualHostdev(detach));
+                                             virDomainNetGetActualHostdev(detach),\
+                                             async);
         goto cleanup;
     }
 
@@ -5442,7 +5491,8 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
      */
     ignore_value(qemuInterfaceStopDevice(detach));
 
-    qemuDomainMarkDeviceForRemoval(vm, &detach->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
@@ -5454,11 +5504,16 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveNetDevice(driver, vm, detach);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveNetDevice(driver, vm, detach);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
 
@@ -5585,7 +5640,8 @@ int qemuDomainDetachLease(virQEMUDriverPtr driver,
 
 int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
-                              virDomainChrDefPtr chr)
+                              virDomainChrDefPtr chr,
+                              bool async)
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -5609,7 +5665,8 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
     if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
         goto cleanup;
 
-    qemuDomainMarkDeviceForRemoval(vm, &tmpChr->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &tmpChr->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
@@ -5619,11 +5676,16 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     VIR_FREE(devstr);
     return ret;
 }
@@ -5632,7 +5694,8 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
 int
 qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
                           virDomainObjPtr vm,
-                          virDomainRNGDefPtr rng)
+                          virDomainRNGDefPtr rng,
+                          bool async)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     ssize_t idx;
@@ -5656,18 +5719,24 @@ qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &tmpRNG->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &tmpRNG->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorDelDevice(priv->mon, tmpRNG->info.alias);
     if (qemuDomainObjExitMonitor(driver, vm) || rc < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveRNGDevice(driver, vm, tmpRNG);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveRNGDevice(driver, vm, tmpRNG);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
 
@@ -5675,7 +5744,8 @@ qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
 int
 qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
                              virDomainObjPtr vm,
-                             virDomainMemoryDefPtr memdef)
+                             virDomainMemoryDefPtr memdef,
+                             bool async)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainMemoryDefPtr mem;
@@ -5701,18 +5771,24 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &mem->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &mem->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorDelDevice(priv->mon, mem->info.alias);
     if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveMemoryDevice(driver, vm, mem);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveMemoryDevice(driver, vm, mem);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
 
@@ -6380,7 +6456,8 @@ qemuDomainSetVcpuInternal(virQEMUDriverPtr driver,
 
 int
 qemuDomainDetachInputDevice(virDomainObjPtr vm,
-                            virDomainInputDefPtr def)
+                            virDomainInputDefPtr def,
+                            bool async)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virQEMUDriverPtr driver = priv->driver;
@@ -6410,7 +6487,8 @@ qemuDomainDetachInputDevice(virDomainObjPtr vm,
         break;
     }
 
-    qemuDomainMarkDeviceForRemoval(vm, &input->info);
+    if (!async)
+        qemuDomainMarkDeviceForRemoval(vm, &input->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, input->info.alias)) {
@@ -6420,10 +6498,15 @@ qemuDomainDetachInputDevice(virDomainObjPtr vm,
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-        ret = qemuDomainRemoveInputDevice(vm, input);
+    if (async) {
+        ret = 0;
+    } else {
+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+            ret = qemuDomainRemoveInputDevice(vm, input);
+    }
 
  cleanup:
-    qemuDomainResetDeviceRemoval(vm);
+    if (!async)
+        qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index b2f5fa688b..751cbf61d4 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -87,7 +87,8 @@ int qemuDomainAttachMemory(virQEMUDriverPtr driver,
                            virDomainMemoryDefPtr mem);
 int qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
                                  virDomainObjPtr vm,
-                                 virDomainMemoryDefPtr memdef);
+                                 virDomainMemoryDefPtr memdef,
+                                 bool async);
 int qemuDomainChangeGraphics(virQEMUDriverPtr driver,
                              virDomainObjPtr vm,
                              virDomainGraphicsDefPtr dev);
@@ -106,26 +107,33 @@ int qemuDomainChangeNetLinkState(virQEMUDriverPtr driver,
                                  int linkstate);
 int qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
                                    virDomainObjPtr vm,
-                                   virDomainDeviceDefPtr dev);
+                                   virDomainDeviceDefPtr dev,
+                                   bool async);
 int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
                                      virDomainObjPtr vm,
-                                     virDomainDeviceDefPtr dev);
+                                     virDomainDeviceDefPtr dev,
+                                     bool async);
 int qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
-                              virDomainDeviceDefPtr dev);
+                              virDomainDeviceDefPtr dev,
+                              bool async);
 int qemuDomainDetachHostDevice(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-                               virDomainDeviceDefPtr dev);
+                               virDomainDeviceDefPtr dev,
+                               bool async);
 int qemuDomainDetachShmemDevice(virQEMUDriverPtr driver,
                                 virDomainObjPtr vm,
-                                virDomainShmemDefPtr dev);
+                                virDomainShmemDefPtr dev,
+                                bool async);
 int qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
                              virDomainObjPtr vm,
-                             virDomainWatchdogDefPtr watchdog);
+                             virDomainWatchdogDefPtr watchdog,
+                             bool async);
 
 int qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
                                    virDomainObjPtr vm,
-                                   virDomainRedirdevDefPtr dev);
+                                   virDomainRedirdevDefPtr dev,
+                                   bool async);
 
 int qemuDomainAttachInputDevice(virQEMUDriverPtr driver,
                                 virDomainObjPtr vm,
@@ -142,13 +150,15 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
                               virDomainChrDefPtr chr);
 int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
-                              virDomainChrDefPtr chr);
+                              virDomainChrDefPtr chr,
+                              bool async);
 int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               virDomainRNGDefPtr rng);
 int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
-                              virDomainRNGDefPtr rng);
+                              virDomainRNGDefPtr rng,
+                              bool async);
 
 void qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
@@ -184,6 +194,7 @@ int qemuDomainSetVcpuInternal(virQEMUDriverPtr driver,
                               bool state);
 
 int qemuDomainDetachInputDevice(virDomainObjPtr vm,
-                                virDomainInputDefPtr def);
+                                virDomainInputDefPtr def,
+                                bool async);
 
 #endif /* __QEMU_HOTPLUG_H__ */
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
index e93503812a..663e33ed00 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -142,22 +142,23 @@ testQemuHotplugAttach(virDomainObjPtr vm,
 
 static int
 testQemuHotplugDetach(virDomainObjPtr vm,
-                      virDomainDeviceDefPtr dev)
+                      virDomainDeviceDefPtr dev,
+                      bool async)
 {
     int ret = -1;
 
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
-        ret = qemuDomainDetachDeviceDiskLive(&driver, vm, dev);
+        ret = qemuDomainDetachDeviceDiskLive(&driver, vm, dev, async);
         break;
     case VIR_DOMAIN_DEVICE_CHR:
-        ret = qemuDomainDetachChrDevice(&driver, vm, dev->data.chr);
+        ret = qemuDomainDetachChrDevice(&driver, vm, dev->data.chr, async);
         break;
     case VIR_DOMAIN_DEVICE_SHMEM:
-        ret = qemuDomainDetachShmemDevice(&driver, vm, dev->data.shmem);
+        ret = qemuDomainDetachShmemDevice(&driver, vm, dev->data.shmem, async);
         break;
     case VIR_DOMAIN_DEVICE_WATCHDOG:
-        ret = qemuDomainDetachWatchdog(&driver, vm, dev->data.watchdog);
+        ret = qemuDomainDetachWatchdog(&driver, vm, dev->data.watchdog, async);
         break;
     default:
         VIR_TEST_VERBOSE("device type '%s' cannot be detached\n",
@@ -322,7 +323,7 @@ testQemuHotplug(const void *data)
         break;
 
     case DETACH:
-        ret = testQemuHotplugDetach(vm, dev);
+        ret = testQemuHotplugDetach(vm, dev, false);
         if (ret == 0 || fail)
             ret = testQemuHotplugCheckResult(vm, domain_xml,
                                              domain_filename, fail);
-- 
2.16.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 10/12] qemu_hotplug: Allow asynchronous detach
Posted by Ján Tomko 6 years, 11 months ago
On Thu, May 24, 2018 at 01:13:37PM +0200, Michal Privoznik wrote:
>diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
>index e84dc909b9..5b5c27b011 100644
>--- a/src/qemu/qemu_hotplug.c
>+++ b/src/qemu/qemu_hotplug.c
>@@ -5414,7 +5462,8 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
>
>     if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
>         ret = qemuDomainDetachThisHostDevice(driver, vm,
>-                                             virDomainNetGetActualHostdev(detach));
>+                                             virDomainNetGetActualHostdev(detach),\

Spurious backslash.

Jano

>+                                             async);
>         goto cleanup;
>     }
>
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 10/12] qemu_hotplug: Allow asynchronous detach
Posted by Ján Tomko 6 years, 11 months ago
On Thu, May 24, 2018 at 01:13:37PM +0200, Michal Privoznik wrote:
>The virDomainDetachDeviceAlias API is designed so that it only
>sends detach request to qemu. It's user's responsibility to wait

s/user/the user/

>for DEVICE_DELETED event, not libvirt's. Add @async flag to
>qemuDomainDetach*Device() functions so that caller can chose if
>detach is semi-synchronous (old virDomainDetachDeviceFlags()) or
>fully asynchronous (new virDomainDetachDeviceFlags()).
>
>Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
>---
> src/qemu/qemu_driver.c  |  32 +++----
> src/qemu/qemu_hotplug.c | 231 ++++++++++++++++++++++++++++++++----------------
> src/qemu/qemu_hotplug.h |  33 ++++---
> tests/qemuhotplugtest.c |  13 +--
> 4 files changed, 203 insertions(+), 106 deletions(-)
>
>@@ -4769,18 +4771,24 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
>     if (qemuDomainObjExitMonitor(driver, vm) < 0)
>         goto cleanup;
>
>-    if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
>-        ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
>+    if (async) {
>+        ret = 0;
>+    } else {
>+        if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
>+            ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
>+    }

I'm sure the ret assignments could be reduced here, but that's out of
scope of this series...

Also, most of the code is executed if (!async). It might be nicer to
come up with a variable that can be used in a positive condition,
but it would be less precise, because only the new async API is
reasonably defined - even if (wait) does not seem to outweigh
the loss of clarity.

>
>  cleanup:
>-    qemuDomainResetDeviceRemoval(vm);
>+    if (!async)
>+        qemuDomainResetDeviceRemoval(vm);
>     return ret;
> }
>
> static int
> qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
>                            virDomainObjPtr vm,
>-                           virDomainDiskDefPtr detach)
>+                           virDomainDiskDefPtr detach,
>+                           bool async)
> {
>     int ret = -1;
>     qemuDomainObjPrivatePtr priv = vm->privateData;
>@@ -5336,7 +5375,8 @@ qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
>         return -1;
>     }
>
>-    qemuDomainMarkDeviceForRemoval(vm, &watchdog->info);
>+    if (!async)
>+        qemuDomainMarkDeviceForRemoval(vm, &watchdog->info);
>
>     qemuDomainObjEnterMonitor(driver, vm);
>     if (qemuMonitorDelDevice(priv->mon, watchdog->info.alias) < 0) {

Missing condition around qemuDomainWaitForDeviceRemoval here in
qemuDomainDetachWatchdog. It should only be called if (!async).

With that fixed:

Reviewed-by: Ján Tomko <jtomko@redhat.com>

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