[libvirt] [PATCH 3/6] qemu: Add option to treat missing USB devices as success

Jiri Denemark jdenemar at redhat.com
Tue Oct 9 12:13:24 UTC 2012


All USB device lookup functions emit an error when they cannot find the
requested device. With this patch, their caller can choose if a missing
device is an error or normal condition.
---
 src/conf/domain_conf.h          |  1 +
 src/qemu/qemu_hostdev.c         | 57 ++++++++++++++++----------
 src/qemu/qemu_hostdev.h         |  4 +-
 src/qemu/qemu_hotplug.c         |  2 +-
 src/security/security_dac.c     | 16 ++++++--
 src/security/security_selinux.c | 16 ++++++--
 src/util/hostusb.c              | 91 ++++++++++++++++++++++++++++++-----------
 src/util/hostusb.h              | 22 ++++++----
 8 files changed, 145 insertions(+), 64 deletions(-)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fa5d1f4..3cb1193 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -386,6 +386,7 @@ struct _virDomainHostdevDef {
     int mode; /* enum virDomainHostdevMode */
     int startupPolicy; /* enum virDomainStartupPolicy */
     unsigned int managed : 1;
+    unsigned int missing : 1;
     union {
         virDomainHostdevSubsys subsys;
         struct {
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 017f0ec..32c858b 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -641,42 +641,57 @@ error:
     return -1;
 }
 
-usbDevice *
-qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev)
+int
+qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
+                         bool mandatory,
+                         usbDevice **usb)
 {
-    usbDevice *usb = NULL;
     unsigned vendor = hostdev->source.subsys.u.usb.vendor;
     unsigned product = hostdev->source.subsys.u.usb.product;
     unsigned bus = hostdev->source.subsys.u.usb.bus;
     unsigned device = hostdev->source.subsys.u.usb.device;
+    int rc;
 
-    if (vendor && bus) {
-        usb = usbFindDevice(vendor, product, bus, device);
+    *usb = NULL;
 
+    if (vendor && bus) {
+        rc = usbFindDevice(vendor, product, bus, device, mandatory, usb);
+        if (rc < 0)
+            return -1;
     } else if (vendor && !bus) {
-        usbDeviceList *devs = usbFindDeviceByVendor(vendor, product);
-        if (!devs)
-            return NULL;
+        usbDeviceList *devs;
 
-        if (usbDeviceListCount(devs) > 1) {
-            virReportError(VIR_ERR_OPERATION_FAILED,
-                           _("multiple USB devices for %x:%x, "
-                             "use <address> to specify one"), vendor, product);
-            usbDeviceListFree(devs);
-            return NULL;
+        rc = usbFindDeviceByVendor(vendor, product, mandatory, &devs);
+        if (rc < 0)
+            return -1;
+
+        if (rc == 1) {
+            *usb = usbDeviceListGet(devs, 0);
+            usbDeviceListSteal(devs, *usb);
         }
-        usb = usbDeviceListGet(devs, 0);
-        usbDeviceListSteal(devs, usb);
         usbDeviceListFree(devs);
 
-        hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
-        hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
+        if (rc == 0) {
+            goto out;
+        } else if (rc > 1) {
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("multiple USB devices for %x:%x, "
+                             "use <address> to specify one"),
+                           vendor, product);
+            return -1;
+        }
 
+        hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(*usb);
+        hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(*usb);
     } else if (!vendor && bus) {
-        usb = usbFindDeviceByBus(bus, device);
+        if (usbFindDeviceByBus(bus, device, mandatory, usb) < 0)
+            return -1;
     }
 
-    return usb;
+out:
+    if (!*usb)
+        hostdev->missing = 1;
+    return 0;
 }
 
 static int
@@ -708,7 +723,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
         if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
             continue;
 
-        if (!(usb = qemuFindHostdevUSBDevice(hostdev)))
+        if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0)
             goto cleanup;
 
         if (usbDeviceListAdd(list, usb) < 0) {
diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h
index 204b2d4..74dd2ce 100644
--- a/src/qemu/qemu_hostdev.h
+++ b/src/qemu/qemu_hostdev.h
@@ -36,7 +36,9 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
                                  const unsigned char *uuid,
                                  virDomainHostdevDefPtr *hostdevs,
                                  int nhostdevs);
-usbDevice *qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev);
+int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
+                             bool mandatory,
+                             usbDevice **usb);
 int qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
                                  const char *name,
                                  usbDeviceList *list);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 59de8e4..2ff9e7a 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1149,7 +1149,7 @@ int qemuDomainAttachHostDevice(struct qemud_driver *driver,
         goto cleanup;
 
     if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
-        if (!(usb = qemuFindHostdevUSBDevice(hostdev)))
+        if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0)
             goto cleanup;
 
         if (usbDeviceListAdd(list, usb) < 0) {
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 22edba2..f126aa5 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -495,9 +495,13 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
 
     switch (dev->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
-        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
-                                      dev->source.subsys.u.usb.device);
+        usbDevice *usb;
 
+        if (dev->missing)
+            return 0;
+
+        usb = usbGetDevice(dev->source.subsys.u.usb.bus,
+                           dev->source.subsys.u.usb.device);
         if (!usb)
             goto done;
 
@@ -568,9 +572,13 @@ virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
 
     switch (dev->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
-        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
-                                      dev->source.subsys.u.usb.device);
+        usbDevice *usb;
+
+        if (dev->missing)
+            return 0;
 
+        usb = usbGetDevice(dev->source.subsys.u.usb.bus,
+                           dev->source.subsys.u.usb.device);
         if (!usb)
             goto done;
 
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 883a82b..d55c60d 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -1101,9 +1101,13 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN
 
     switch (dev->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
-        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
-                                      dev->source.subsys.u.usb.device);
+        usbDevice *usb;
 
+        if (dev->missing)
+            return 0;
+
+        usb = usbGetDevice(dev->source.subsys.u.usb.bus,
+                           dev->source.subsys.u.usb.device);
         if (!usb)
             goto done;
 
@@ -1174,9 +1178,13 @@ virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUT
 
     switch (dev->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
-        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
-                                      dev->source.subsys.u.usb.device);
+        usbDevice *usb;
+
+        if (dev->missing)
+            return 0;
 
+        usb = usbGetDevice(dev->source.subsys.u.usb.bus,
+                           dev->source.subsys.u.usb.device);
         if (!usb)
             goto done;
 
diff --git a/src/util/hostusb.c b/src/util/hostusb.c
index f0196a8..81a9f5a 100644
--- a/src/util/hostusb.c
+++ b/src/util/hostusb.c
@@ -186,76 +186,117 @@ cleanup:
     return ret;
 }
 
-usbDeviceList *
-usbFindDeviceByVendor(unsigned int vendor, unsigned product)
+int
+usbFindDeviceByVendor(unsigned int vendor,
+                      unsigned product,
+                      bool mandatory,
+                      usbDeviceList **devices)
 {
-
     usbDeviceList *list;
+    int count;
+
     if (!(list = usbDeviceSearch(vendor, product, 0 , 0,
                                  USB_DEVICE_FIND_BY_VENDOR)))
-        return NULL;
+        return -1;
 
     if (list->count == 0) {
+        usbDeviceListFree(list);
+        if (!mandatory) {
+            VIR_DEBUG("Did not find USB device %x:%x",
+                      vendor, product);
+            if (devices)
+                *devices = NULL;
+            return 0;
+        }
+
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Did not find USB device %x:%x"), vendor, product);
-        usbDeviceListFree(list);
-        return NULL;
+        return -1;
     }
 
-    return list;
+    count = list->count;
+    if (devices)
+        *devices = list;
+    else
+        usbDeviceListFree(list);
+
+    return count;
 }
 
-usbDevice *
-usbFindDeviceByBus(unsigned int bus, unsigned devno)
+int
+usbFindDeviceByBus(unsigned int bus,
+                   unsigned devno,
+                   bool mandatory,
+                   usbDevice **usb)
 {
-    usbDevice *usb;
     usbDeviceList *list;
 
     if (!(list = usbDeviceSearch(0, 0, bus, devno,
                                  USB_DEVICE_FIND_BY_BUS)))
-        return NULL;
+        return -1;
 
     if (list->count == 0) {
+        usbDeviceListFree(list);
+        if (!mandatory) {
+            VIR_DEBUG("Did not find USB device bus:%u device:%u",
+                      bus, devno);
+            if (usb)
+                *usb = NULL;
+            return 0;
+        }
+
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Did not find USB device bus:%u device:%u"),
                        bus, devno);
-        usbDeviceListFree(list);
-        return NULL;
+        return -1;
     }
 
-    usb = usbDeviceListGet(list, 0);
-    usbDeviceListSteal(list, usb);
+    if (usb) {
+        *usb = usbDeviceListGet(list, 0);
+        usbDeviceListSteal(list, *usb);
+    }
     usbDeviceListFree(list);
 
-    return usb;
+    return 0;
 }
 
-usbDevice *
+int
 usbFindDevice(unsigned int vendor,
               unsigned int product,
               unsigned int bus,
-              unsigned int devno)
+              unsigned int devno,
+              bool mandatory,
+              usbDevice **usb)
 {
-    usbDevice *usb;
     usbDeviceList *list;
 
     unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS;
     if (!(list = usbDeviceSearch(vendor, product, bus, devno, flags)))
-        return NULL;
+        return -1;
 
     if (list->count == 0) {
+        usbDeviceListFree(list);
+        if (!mandatory) {
+            VIR_DEBUG("Did not find USB device %x:%x bus:%u device:%u",
+                      vendor, product, bus, devno);
+            if (usb)
+                *usb = NULL;
+            return 0;
+        }
+
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Did not find USB device %x:%x bus:%u device:%u"),
                        vendor, product, bus, devno);
-        usbDeviceListFree(list);
-        return NULL;
+        return -1;
     }
 
-    usb = usbDeviceListGet(list, 0);
-    usbDeviceListSteal(list, usb);
+    if (usb) {
+        *usb = usbDeviceListGet(list, 0);
+        usbDeviceListSteal(list, *usb);
+    }
     usbDeviceListFree(list);
 
-    return usb;
+    return 0;
 }
 
 usbDevice *
diff --git a/src/util/hostusb.h b/src/util/hostusb.h
index 6f5067c..4f55fdc 100644
--- a/src/util/hostusb.h
+++ b/src/util/hostusb.h
@@ -31,16 +31,22 @@ typedef struct _usbDeviceList usbDeviceList;
 usbDevice *usbGetDevice(unsigned int bus,
                         unsigned int devno);
 
-usbDevice *usbFindDeviceByBus(unsigned int bus,
-                              unsigned int devno);
+int usbFindDeviceByBus(unsigned int bus,
+                       unsigned int devno,
+                       bool mandatory,
+                       usbDevice **usb);
 
-usbDeviceList *usbFindDeviceByVendor(unsigned int vendor,
-                                     unsigned int product);
+int usbFindDeviceByVendor(unsigned int vendor,
+                          unsigned int product,
+                          bool mandatory,
+                          usbDeviceList **devices);
 
-usbDevice *usbFindDevice(unsigned int vendor,
-                         unsigned int product,
-                         unsigned int bus,
-                         unsigned int devno);
+int usbFindDevice(unsigned int vendor,
+                  unsigned int product,
+                  unsigned int bus,
+                  unsigned int devno,
+                  bool mandatory,
+                  usbDevice **usb);
 
 void       usbFreeDevice (usbDevice *dev);
 void       usbDeviceSetUsedBy(usbDevice *dev, const char *name);
-- 
1.7.12




More information about the libvir-list mailing list