mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 14:15:28 +00:00
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:
parent
7bcc7278bf
commit
059aff6b98
@ -386,6 +386,7 @@ struct _virDomainHostdevDef {
|
|||||||
int mode; /* enum virDomainHostdevMode */
|
int mode; /* enum virDomainHostdevMode */
|
||||||
int startupPolicy; /* enum virDomainStartupPolicy */
|
int startupPolicy; /* enum virDomainStartupPolicy */
|
||||||
unsigned int managed : 1;
|
unsigned int managed : 1;
|
||||||
|
unsigned int missing : 1;
|
||||||
union {
|
union {
|
||||||
virDomainHostdevSubsys subsys;
|
virDomainHostdevSubsys subsys;
|
||||||
struct {
|
struct {
|
||||||
|
@ -641,42 +641,57 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbDevice *
|
int
|
||||||
qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev)
|
qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
|
||||||
|
bool mandatory,
|
||||||
|
usbDevice **usb)
|
||||||
{
|
{
|
||||||
usbDevice *usb = NULL;
|
|
||||||
unsigned vendor = hostdev->source.subsys.u.usb.vendor;
|
unsigned vendor = hostdev->source.subsys.u.usb.vendor;
|
||||||
unsigned product = hostdev->source.subsys.u.usb.product;
|
unsigned product = hostdev->source.subsys.u.usb.product;
|
||||||
unsigned bus = hostdev->source.subsys.u.usb.bus;
|
unsigned bus = hostdev->source.subsys.u.usb.bus;
|
||||||
unsigned device = hostdev->source.subsys.u.usb.device;
|
unsigned device = hostdev->source.subsys.u.usb.device;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
*usb = NULL;
|
||||||
|
|
||||||
if (vendor && bus) {
|
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) {
|
} else if (vendor && !bus) {
|
||||||
usbDeviceList *devs = usbFindDeviceByVendor(vendor, product);
|
usbDeviceList *devs;
|
||||||
if (!devs)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (usbDeviceListCount(devs) > 1) {
|
rc = usbFindDeviceByVendor(vendor, product, mandatory, &devs);
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
if (rc < 0)
|
||||||
_("multiple USB devices for %x:%x, "
|
return -1;
|
||||||
"use <address> to specify one"), vendor, product);
|
|
||||||
usbDeviceListFree(devs);
|
if (rc == 1) {
|
||||||
return NULL;
|
*usb = usbDeviceListGet(devs, 0);
|
||||||
|
usbDeviceListSteal(devs, *usb);
|
||||||
}
|
}
|
||||||
usb = usbDeviceListGet(devs, 0);
|
|
||||||
usbDeviceListSteal(devs, usb);
|
|
||||||
usbDeviceListFree(devs);
|
usbDeviceListFree(devs);
|
||||||
|
|
||||||
hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
|
if (rc == 0) {
|
||||||
hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
|
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) {
|
} 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
|
static int
|
||||||
@ -708,7 +723,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
|
|||||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(usb = qemuFindHostdevUSBDevice(hostdev)))
|
if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (usbDeviceListAdd(list, usb) < 0) {
|
if (usbDeviceListAdd(list, usb) < 0) {
|
||||||
|
@ -36,7 +36,9 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
|
|||||||
const unsigned char *uuid,
|
const unsigned char *uuid,
|
||||||
virDomainHostdevDefPtr *hostdevs,
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
int nhostdevs);
|
int nhostdevs);
|
||||||
usbDevice *qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev);
|
int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
|
||||||
|
bool mandatory,
|
||||||
|
usbDevice **usb);
|
||||||
int qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
|
int qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
|
||||||
const char *name,
|
const char *name,
|
||||||
usbDeviceList *list);
|
usbDeviceList *list);
|
||||||
|
@ -1153,7 +1153,7 @@ int qemuDomainAttachHostDevice(struct qemud_driver *driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
|
if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
|
||||||
if (!(usb = qemuFindHostdevUSBDevice(hostdev)))
|
if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (usbDeviceListAdd(list, usb) < 0) {
|
if (usbDeviceListAdd(list, usb) < 0) {
|
||||||
|
@ -495,9 +495,13 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
|
|||||||
|
|
||||||
switch (dev->source.subsys.type) {
|
switch (dev->source.subsys.type) {
|
||||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
||||||
usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
usbDevice *usb;
|
||||||
dev->source.subsys.u.usb.device);
|
|
||||||
|
|
||||||
|
if (dev->missing)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
||||||
|
dev->source.subsys.u.usb.device);
|
||||||
if (!usb)
|
if (!usb)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -568,9 +572,13 @@ virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
|
|||||||
|
|
||||||
switch (dev->source.subsys.type) {
|
switch (dev->source.subsys.type) {
|
||||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
||||||
usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
usbDevice *usb;
|
||||||
dev->source.subsys.u.usb.device);
|
|
||||||
|
|
||||||
|
if (dev->missing)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
||||||
|
dev->source.subsys.u.usb.device);
|
||||||
if (!usb)
|
if (!usb)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -1101,9 +1101,13 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN
|
|||||||
|
|
||||||
switch (dev->source.subsys.type) {
|
switch (dev->source.subsys.type) {
|
||||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
||||||
usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
usbDevice *usb;
|
||||||
dev->source.subsys.u.usb.device);
|
|
||||||
|
|
||||||
|
if (dev->missing)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
||||||
|
dev->source.subsys.u.usb.device);
|
||||||
if (!usb)
|
if (!usb)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -1174,9 +1178,13 @@ virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUT
|
|||||||
|
|
||||||
switch (dev->source.subsys.type) {
|
switch (dev->source.subsys.type) {
|
||||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
||||||
usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
usbDevice *usb;
|
||||||
dev->source.subsys.u.usb.device);
|
|
||||||
|
|
||||||
|
if (dev->missing)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
||||||
|
dev->source.subsys.u.usb.device);
|
||||||
if (!usb)
|
if (!usb)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -186,76 +186,117 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbDeviceList *
|
int
|
||||||
usbFindDeviceByVendor(unsigned int vendor, unsigned product)
|
usbFindDeviceByVendor(unsigned int vendor,
|
||||||
|
unsigned product,
|
||||||
|
bool mandatory,
|
||||||
|
usbDeviceList **devices)
|
||||||
{
|
{
|
||||||
|
|
||||||
usbDeviceList *list;
|
usbDeviceList *list;
|
||||||
|
int count;
|
||||||
|
|
||||||
if (!(list = usbDeviceSearch(vendor, product, 0 , 0,
|
if (!(list = usbDeviceSearch(vendor, product, 0 , 0,
|
||||||
USB_DEVICE_FIND_BY_VENDOR)))
|
USB_DEVICE_FIND_BY_VENDOR)))
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
if (list->count == 0) {
|
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,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Did not find USB device %x:%x"), vendor, product);
|
_("Did not find USB device %x:%x"), vendor, product);
|
||||||
usbDeviceListFree(list);
|
return -1;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
count = list->count;
|
||||||
|
if (devices)
|
||||||
|
*devices = list;
|
||||||
|
else
|
||||||
|
usbDeviceListFree(list);
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbDevice *
|
int
|
||||||
usbFindDeviceByBus(unsigned int bus, unsigned devno)
|
usbFindDeviceByBus(unsigned int bus,
|
||||||
|
unsigned devno,
|
||||||
|
bool mandatory,
|
||||||
|
usbDevice **usb)
|
||||||
{
|
{
|
||||||
usbDevice *usb;
|
|
||||||
usbDeviceList *list;
|
usbDeviceList *list;
|
||||||
|
|
||||||
if (!(list = usbDeviceSearch(0, 0, bus, devno,
|
if (!(list = usbDeviceSearch(0, 0, bus, devno,
|
||||||
USB_DEVICE_FIND_BY_BUS)))
|
USB_DEVICE_FIND_BY_BUS)))
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
if (list->count == 0) {
|
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,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Did not find USB device bus:%u device:%u"),
|
_("Did not find USB device bus:%u device:%u"),
|
||||||
bus, devno);
|
bus, devno);
|
||||||
usbDeviceListFree(list);
|
return -1;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usb = usbDeviceListGet(list, 0);
|
if (usb) {
|
||||||
usbDeviceListSteal(list, usb);
|
*usb = usbDeviceListGet(list, 0);
|
||||||
|
usbDeviceListSteal(list, *usb);
|
||||||
|
}
|
||||||
usbDeviceListFree(list);
|
usbDeviceListFree(list);
|
||||||
|
|
||||||
return usb;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbDevice *
|
int
|
||||||
usbFindDevice(unsigned int vendor,
|
usbFindDevice(unsigned int vendor,
|
||||||
unsigned int product,
|
unsigned int product,
|
||||||
unsigned int bus,
|
unsigned int bus,
|
||||||
unsigned int devno)
|
unsigned int devno,
|
||||||
|
bool mandatory,
|
||||||
|
usbDevice **usb)
|
||||||
{
|
{
|
||||||
usbDevice *usb;
|
|
||||||
usbDeviceList *list;
|
usbDeviceList *list;
|
||||||
|
|
||||||
unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS;
|
unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS;
|
||||||
if (!(list = usbDeviceSearch(vendor, product, bus, devno, flags)))
|
if (!(list = usbDeviceSearch(vendor, product, bus, devno, flags)))
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
if (list->count == 0) {
|
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,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Did not find USB device %x:%x bus:%u device:%u"),
|
_("Did not find USB device %x:%x bus:%u device:%u"),
|
||||||
vendor, product, bus, devno);
|
vendor, product, bus, devno);
|
||||||
usbDeviceListFree(list);
|
return -1;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usb = usbDeviceListGet(list, 0);
|
if (usb) {
|
||||||
usbDeviceListSteal(list, usb);
|
*usb = usbDeviceListGet(list, 0);
|
||||||
|
usbDeviceListSteal(list, *usb);
|
||||||
|
}
|
||||||
usbDeviceListFree(list);
|
usbDeviceListFree(list);
|
||||||
|
|
||||||
return usb;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbDevice *
|
usbDevice *
|
||||||
|
@ -31,16 +31,22 @@ typedef struct _usbDeviceList usbDeviceList;
|
|||||||
usbDevice *usbGetDevice(unsigned int bus,
|
usbDevice *usbGetDevice(unsigned int bus,
|
||||||
unsigned int devno);
|
unsigned int devno);
|
||||||
|
|
||||||
usbDevice *usbFindDeviceByBus(unsigned int bus,
|
int usbFindDeviceByBus(unsigned int bus,
|
||||||
unsigned int devno);
|
unsigned int devno,
|
||||||
|
bool mandatory,
|
||||||
|
usbDevice **usb);
|
||||||
|
|
||||||
usbDeviceList *usbFindDeviceByVendor(unsigned int vendor,
|
int usbFindDeviceByVendor(unsigned int vendor,
|
||||||
unsigned int product);
|
unsigned int product,
|
||||||
|
bool mandatory,
|
||||||
|
usbDeviceList **devices);
|
||||||
|
|
||||||
usbDevice *usbFindDevice(unsigned int vendor,
|
int usbFindDevice(unsigned int vendor,
|
||||||
unsigned int product,
|
unsigned int product,
|
||||||
unsigned int bus,
|
unsigned int bus,
|
||||||
unsigned int devno);
|
unsigned int devno,
|
||||||
|
bool mandatory,
|
||||||
|
usbDevice **usb);
|
||||||
|
|
||||||
void usbFreeDevice (usbDevice *dev);
|
void usbFreeDevice (usbDevice *dev);
|
||||||
void usbDeviceSetUsedBy(usbDevice *dev, const char *name);
|
void usbDeviceSetUsedBy(usbDevice *dev, const char *name);
|
||||||
|
Loading…
Reference in New Issue
Block a user