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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list