[libvirt] [PATCH v3 REBASE 2 06/12] qemu: handle libvirtd restart after host usb device unplug

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Tue Oct 29 08:17:57 UTC 2019


It is possible for libvirtd to go down before DEVICE_DELETED event is
delivered upon usb hostdev unplug and to receive the event after the
libvirtd is up. In order to handle this case we need to save
usb hostdev deleteAction in status file.

Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413 at gmail.com>
---
 src/conf/domain_conf.c | 26 ++++++++++++++++++++++++++
 src/conf/domain_conf.h |  1 +
 src/qemu/qemu_driver.c | 20 ++++++++++++++++++--
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 781764225e..06a23cd127 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1244,6 +1244,13 @@ VIR_ENUM_IMPL(virDomainShmemModel,
               "ivshmem-doorbell",
 );
 
+VIR_ENUM_IMPL(virDomainHostdevDeleteAction,
+              VIR_DOMAIN_HOSTDEV_DELETE_ACTION_LAST,
+              "none",
+              "delete",
+              "unplug"
+);
+
 VIR_ENUM_IMPL(virDomainLaunchSecurity,
               VIR_DOMAIN_LAUNCH_SECURITY_LAST,
               "",
@@ -7585,6 +7592,7 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
     virDomainHostdevSubsysUSBPtr usbsrc = &def->source.subsys.u.usb;
     g_autofree char *startupPolicy = NULL;
     g_autofree char *autoAddress = NULL;
+    g_autofree char *deleteAction = NULL;
 
     if ((startupPolicy = virXMLPropString(node, "startupPolicy"))) {
         def->startupPolicy =
@@ -7602,6 +7610,18 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
             usbsrc->autoAddress = true;
     }
 
+    if ((deleteAction = virXMLPropString(node, "deleteAction"))) {
+        def->deleteAction =
+            virDomainHostdevDeleteActionTypeFromString(deleteAction);
+
+        if (def->deleteAction <= 0) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Unknown deleteAction '%s'"),
+                           deleteAction);
+            goto out;
+        }
+    }
+
     /* Product can validly be 0, so we need some extra help to determine
      * if it is uninitialized*/
     got_product = false;
@@ -25024,6 +25044,12 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
 
         if (def->missing && !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
             virBufferAddLit(buf, " missing='yes'");
+
+        if (def->deleteAction && (flags & VIR_DOMAIN_DEF_FORMAT_STATUS)) {
+            const char *deleteAction;
+            deleteAction = virDomainHostdevDeleteActionTypeToString(def->deleteAction);
+            virBufferAsprintf(buf, " deleteAction='%s'", deleteAction);
+        }
     }
 
     if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1e3e500360..652ce669a6 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -340,6 +340,7 @@ typedef enum {
 
     VIR_DOMAIN_HOSTDEV_DELETE_ACTION_LAST
 } virDomainHostdevDeleteActionType;
+VIR_ENUM_DECL(virDomainHostdevDeleteAction);
 
 
 /* basic device for direct passthrough */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bcc3ff11e0..fe6b94045b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5067,10 +5067,13 @@ processUSBAddedEvent(virQEMUDriverPtr driver,
 {
     virDomainHostdevDefPtr hostdev;
     virDomainHostdevSubsysUSBPtr usbsrc;
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     size_t i;
 
-    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
+        virObjectUnref(cfg);
         return;
+    }
 
     if (!virDomainObjIsActive(vm)) {
         VIR_DEBUG("Domain is not running");
@@ -5098,8 +5101,13 @@ processUSBAddedEvent(virQEMUDriverPtr driver,
     if (qemuDomainAttachHostDevice(driver, vm, hostdev) < 0)
         goto cleanup;
 
+    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
+        VIR_WARN("unable to save domain status after plugging device %s",
+                 hostdev->info->alias);
+
  cleanup:
     qemuDomainObjEndJob(driver, vm);
+    virObjectUnref(cfg);
 }
 
 
@@ -5111,9 +5119,12 @@ processUSBRemovedEvent(virQEMUDriverPtr driver,
     size_t i;
     virDomainHostdevDefPtr hostdev;
     virDomainDeviceDef dev = { .type = VIR_DOMAIN_DEVICE_HOSTDEV };
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
 
-    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
+        virObjectUnref(cfg);
         return;
+    }
 
     if (!virDomainObjIsActive(vm)) {
         VIR_DEBUG("Domain is not running");
@@ -5149,8 +5160,13 @@ processUSBRemovedEvent(virQEMUDriverPtr driver,
     if (qemuDomainDetachDeviceLive(vm, &dev, driver, true, true) < 0)
         goto cleanup;
 
+    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
+        VIR_WARN("unable to save domain status after unplugging device %s",
+                 hostdev->info->alias);
+
  cleanup:
     qemuDomainObjEndJob(driver, vm);
+    virObjectUnref(cfg);
 }
 
 
-- 
2.23.0




More information about the libvir-list mailing list