[libvirt] [PATCH v2 01/11] qemu: track hostdev delete intention

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Mon Sep 9 11:33:04 UTC 2019


We are going to call qemuDomainDetachDeviceLive when usb device
is unplugged from host. But later when DEVICE_DELETED event is delivered
we need to keep device in libvirt config. For this purpuse let's save
delete intention in device config.

Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
---
 src/conf/domain_conf.h  | 14 ++++++++++++++
 src/qemu/qemu_driver.c  |  4 ++--
 src/qemu/qemu_hotplug.c | 23 ++++++++++++++++++++---
 src/qemu/qemu_hotplug.h |  3 ++-
 tests/qemuhotplugtest.c |  2 +-
 5 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 33cef5b75c..19a5b21462 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -326,6 +326,19 @@ struct _virDomainHostdevCaps {
     } u;
 };
 
+typedef enum {
+    VIR_DOMAIN_HOSTDEV_DELETE_ACTION_NONE = 0,
+    /* delete associated device from libvirt config
+     * as intended by client API call */
+    VIR_DOMAIN_HOSTDEV_DELETE_ACTION_DELETE,
+    /* keep associated device in libvirt config as
+     * qemu device is deleted as a result of unplugging
+     * device from host */
+    VIR_DOMAIN_HOSTDEV_DELETE_ACTION_UNPLUG,
+
+    VIR_DOMAIN_HOSTDEV_DELETE_ACTION_LAST
+} virDomainHostdevDeleteActionType;
+
 
 /* basic device for direct passthrough */
 struct _virDomainHostdevDef {
@@ -343,6 +356,7 @@ struct _virDomainHostdevDef {
     bool missing;
     bool readonly;
     bool shareable;
+    virDomainHostdevDeleteActionType deleteAction;
     union {
         virDomainHostdevSubsys subsys;
         virDomainHostdevCaps caps;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 78f5471b79..2378a2e7d0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9123,7 +9123,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver,
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
         int rc;
 
-        if ((rc = qemuDomainDetachDeviceLive(vm, dev_copy, driver, false)) < 0)
+        if ((rc = qemuDomainDetachDeviceLive(vm, dev_copy, driver, false, false)) < 0)
             goto cleanup;
 
         if (rc == 0 && qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
@@ -9212,7 +9212,7 @@ qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver,
         if (virDomainDefFindDevice(def, alias, &dev, true) < 0)
             goto cleanup;
 
-        if ((rc = qemuDomainDetachDeviceLive(vm, &dev, driver, true)) < 0)
+        if ((rc = qemuDomainDetachDeviceLive(vm, &dev, driver, true, false)) < 0)
             goto cleanup;
 
         if (rc == 0 && qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 63acb9c451..559254b234 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -5348,7 +5348,8 @@ qemuDomainDetachPrepController(virDomainObjPtr vm,
 static int
 qemuDomainDetachPrepHostdev(virDomainObjPtr vm,
                             virDomainHostdevDefPtr match,
-                            virDomainHostdevDefPtr *detach)
+                            virDomainHostdevDefPtr *detach,
+                            bool unplug)
 {
     virDomainHostdevSubsysPtr subsys = &match->source.subsys;
     virDomainHostdevSubsysUSBPtr usbsrc = &subsys->u.usb;
@@ -5420,6 +5421,20 @@ qemuDomainDetachPrepHostdev(virDomainObjPtr vm,
         return -1;
     }
 
+    /*
+     * Why having additional check in second branch? Suppose client
+     * asks for device detaching and we delete device from qemu
+     * but don't get DEVICE_DELETED event yet. Next USB is unplugged
+     * from host and we have this function called again. If we reset
+     * delete action to 'unplug' then device will be left in
+     * libvirt config after handling DEVICE_DELETED event while
+     * it should not as client asked to detach the device before.
+     */
+    if (!unplug)
+        hostdev->deleteAction = VIR_DOMAIN_HOSTDEV_DELETE_ACTION_DELETE;
+    else if (hostdev->deleteAction != VIR_DOMAIN_HOSTDEV_DELETE_ACTION_DELETE)
+        hostdev->deleteAction = VIR_DOMAIN_HOSTDEV_DELETE_ACTION_UNPLUG;
+
     return 0;
 }
 
@@ -5721,7 +5736,8 @@ int
 qemuDomainDetachDeviceLive(virDomainObjPtr vm,
                            virDomainDeviceDefPtr match,
                            virQEMUDriverPtr driver,
-                           bool async)
+                           bool async,
+                           bool unplug)
 {
     virDomainDeviceDef detach = { .type = match->type };
     virDomainDeviceInfoPtr info = NULL;
@@ -5766,7 +5782,8 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
         break;
     case VIR_DOMAIN_DEVICE_HOSTDEV:
         if (qemuDomainDetachPrepHostdev(vm, match->data.hostdev,
-                                        &detach.data.hostdev) < 0) {
+                                        &detach.data.hostdev,
+                                        unplug) < 0) {
             return -1;
         }
         break;
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 896e6c7b98..f7ebf3f505 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -116,7 +116,8 @@ int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
 int qemuDomainDetachDeviceLive(virDomainObjPtr vm,
                                virDomainDeviceDefPtr match,
                                virQEMUDriverPtr driver,
-                               bool async);
+                               bool async,
+                               bool unplug);
 
 void qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
index b6aad330a9..ef91d4f131 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -151,7 +151,7 @@ testQemuHotplugDetach(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_CHR:
     case VIR_DOMAIN_DEVICE_SHMEM:
     case VIR_DOMAIN_DEVICE_WATCHDOG:
-        ret = qemuDomainDetachDeviceLive(vm, dev, &driver, async);
+        ret = qemuDomainDetachDeviceLive(vm, dev, &driver, async, false);
         break;
     default:
         VIR_TEST_VERBOSE("device type '%s' cannot be detached",
-- 
2.23.0




More information about the libvir-list mailing list