From: Jiri Denemark Date: Wed, 3 Oct 2012 14:57:28 +0000 (+0200) Subject: qemu: Add option to treat missing USB devices as success X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=059aff6b9860b18634709bc76d64ea78f7e609db;p=libvirt.git qemu: Add option to treat missing USB devices as success 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. --- diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 381860c0a9..6f4dc5c72c 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 017f0ec6f3..32c858bd7c 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
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
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 204b2d4966..74dd2ce7d6 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 3a2881e93f..78f1278cec 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -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) { diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 22edba22e0..f126aa5410 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 883a82bf88..d55c60dd04 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 f0196a848f..81a9f5ab55 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 6f5067cf56..4f55fdc5bf 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);