]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Add option to treat missing USB devices as success
authorJiri Denemark <jdenemar@redhat.com>
Wed, 3 Oct 2012 14:57:28 +0000 (16:57 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Thu, 11 Oct 2012 13:11:41 +0000 (15:11 +0200)
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
src/qemu/qemu_hostdev.c
src/qemu/qemu_hostdev.h
src/qemu/qemu_hotplug.c
src/security/security_dac.c
src/security/security_selinux.c
src/util/hostusb.c
src/util/hostusb.h

index 381860c0a9c4be91a3cf2ca5cd8f7da8d1342f96..6f4dc5c72c623322f1b1fd01b7cb756f476816d9 100644 (file)
@@ -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 {
index 017f0ec6f3c89509d68f78a43c5b3db7156b5c38..32c858bd7c65ef628bb26d4786636727705b457a 100644 (file)
@@ -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) {
index 204b2d4966f6f2753d7c6b5f7d660b3d4acf56f4..74dd2ce7d6d97a91630d086c0abe049a48594022 100644 (file)
@@ -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);
index 3a2881e93f961629d6f7f32838cd764675d30af5..78f1278cec660875b37ad9777adb6c006748e088 100644 (file)
@@ -1153,7 +1153,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) {
index 22edba22e0f52196b8c911b074a6fda7279c0441..f126aa54104e48135c7a3756910ada4b773fa622 100644 (file)
@@ -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;
 
index 883a82bf88fd6b4dfaf1069bc81b86ec020e2f1d..d55c60dd041402256c626d8b232a2b20664b984c 100644 (file)
@@ -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;
 
index f0196a848f4bac8540dd8d98447e92a4e1c52127..81a9f5ab55645b19dcf0524015b27e275645bf2b 100644 (file)
@@ -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 *
index 6f5067cf56cf6880f8389761904f9d54b85e0b16..4f55fdc5bf49c5f2733a8a4963810bbad5590fbc 100644 (file)
@@ -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);