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.
This commit is contained in:
Jiri Denemark 2012-10-03 16:57:28 +02:00
parent 7bcc7278bf
commit 059aff6b98
8 changed files with 145 additions and 64 deletions

View 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 {

View 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;
*usb = NULL;
if (vendor && bus) {
usb = usbFindDevice(vendor, product, bus, device);
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) {

View 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);

View 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) {

View 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;

View 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;

View 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 *

View 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);