- VUL-1: Fix hotplug support for usb devices with same vendorID,
productID 9914477e-usb-search-funcs.patch 05abd150-usb-improve-hotplug.patch bnc#766559 OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=211
This commit is contained in:
parent
fbf6ff9777
commit
12b4dbbe29
325
05abd150-usb-improve-hotplug.patch
Normal file
325
05abd150-usb-improve-hotplug.patch
Normal file
@ -0,0 +1,325 @@
|
||||
commit 05abd1507d66aabb6cad12eeafeb4c4d1911c585
|
||||
Author: Guannan Ren <gren@redhat.com>
|
||||
Date: Sun May 6 22:45:05 2012 +0800
|
||||
|
||||
qemu: call usb search function for hostdev initialization and hotplug
|
||||
|
||||
src/qemu/qemu_hostdev.c:
|
||||
refactor qemuPrepareHostdevUSBDevices function, make it focus on
|
||||
adding usb device to activeUsbHostdevs after check. After that,
|
||||
the usb hotplug function qemuDomainAttachHostDevice also could use
|
||||
it.
|
||||
expand qemuPrepareHostUSBDevices to perform the usb search,
|
||||
rollback on failure.
|
||||
|
||||
src/qemu/qemu_hotplug.c:
|
||||
If there are multiple usb devices available with same vendorID and productID,
|
||||
but with different value of "bus, device", we give an error to let user
|
||||
use <address> to specify the desired one.
|
||||
|
||||
Index: libvirt-0.9.11.3/src/qemu/qemu_hostdev.c
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/qemu/qemu_hostdev.c
|
||||
+++ libvirt-0.9.11.3/src/qemu/qemu_hostdev.c
|
||||
@@ -565,13 +565,53 @@ qemuPrepareHostPCIDevices(struct qemud_d
|
||||
int
|
||||
qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
|
||||
const char *name,
|
||||
- virDomainHostdevDefPtr *hostdevs,
|
||||
- int nhostdevs)
|
||||
+ usbDeviceList *list)
|
||||
{
|
||||
- int ret = -1;
|
||||
int i;
|
||||
+ unsigned int count;
|
||||
+ usbDevice *tmp;
|
||||
+
|
||||
+ count = usbDeviceListCount(list);
|
||||
+
|
||||
+ for (i = 0; i < count; i++) {
|
||||
+ usbDevice *usb = usbDeviceListGet(list, i);
|
||||
+ if ((tmp = usbDeviceListFind(driver->activeUsbHostdevs, usb))) {
|
||||
+ const char *other_name = usbDeviceGetUsedBy(tmp);
|
||||
+
|
||||
+ if (other_name)
|
||||
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||
+ _("USB device %s is in use by domain %s"),
|
||||
+ usbDeviceGetName(tmp), other_name);
|
||||
+ else
|
||||
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||
+ _("USB device %s is already in use"),
|
||||
+ usbDeviceGetName(tmp));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ usbDeviceSetUsedBy(usb, name);
|
||||
+ VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs",
|
||||
+ usbDeviceGetBus(usb), usbDeviceGetDevno(usb), name);
|
||||
+ /*
|
||||
+ * The caller is responsible to steal these usb devices
|
||||
+ * from the usbDeviceList that passed in on success,
|
||||
+ * perform rollback on failure.
|
||||
+ */
|
||||
+ if (usbDeviceListAdd(driver->activeUsbHostdevs, usb) < 0)
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qemuPrepareHostUSBDevices(struct qemud_driver *driver,
|
||||
+ virDomainDefPtr def)
|
||||
+{
|
||||
+ int i, ret = -1;
|
||||
usbDeviceList *list;
|
||||
usbDevice *tmp;
|
||||
+ virDomainHostdevDefPtr *hostdevs = def->hostdevs;
|
||||
+ int nhostdevs = def->nhostdevs;
|
||||
|
||||
/* To prevent situation where USB device is assigned to two domains
|
||||
* we need to keep a list of currently assigned USB devices.
|
||||
@@ -586,70 +626,61 @@ qemuPrepareHostdevUSBDevices(struct qemu
|
||||
*/
|
||||
for (i = 0 ; i < nhostdevs ; i++) {
|
||||
virDomainHostdevDefPtr hostdev = hostdevs[i];
|
||||
+ usbDevice *usb = NULL;
|
||||
|
||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
||||
continue;
|
||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
||||
continue;
|
||||
|
||||
- /* Resolve a vendor/product to bus/device */
|
||||
- if (hostdev->source.subsys.u.usb.vendor) {
|
||||
- usbDevice *usb;
|
||||
- usbDeviceList *devs;
|
||||
+ 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;
|
||||
|
||||
- devs = usbFindDeviceByVendor(hostdev->source.subsys.u.usb.vendor,
|
||||
- hostdev->source.subsys.u.usb.product);
|
||||
+ if (vendor && bus) {
|
||||
+ usb = usbFindDevice(vendor, product, bus, device);
|
||||
|
||||
+ } else if (vendor && !bus) {
|
||||
+ usbDeviceList *devs = usbFindDeviceByVendor(vendor, product);
|
||||
if (!devs)
|
||||
goto cleanup;
|
||||
|
||||
+ if (usbDeviceListCount(devs) > 1) {
|
||||
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||
+ _("multiple USB devices for %x:%x, "
|
||||
+ "use <address> to specify one"), vendor, product);
|
||||
+ usbDeviceListFree(devs);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
usb = usbDeviceListGet(devs, 0);
|
||||
usbDeviceListSteal(devs, usb);
|
||||
usbDeviceListFree(devs);
|
||||
|
||||
- if ((tmp = usbDeviceListFind(driver->activeUsbHostdevs, usb))) {
|
||||
- const char *other_name = usbDeviceGetUsedBy(tmp);
|
||||
-
|
||||
- if (other_name)
|
||||
- qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||
- _("USB device %s is in use by domain %s"),
|
||||
- usbDeviceGetName(tmp), other_name);
|
||||
- else
|
||||
- qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||
- _("USB device %s is already in use"),
|
||||
- usbDeviceGetName(tmp));
|
||||
- usbFreeDevice(usb);
|
||||
- goto cleanup;
|
||||
- }
|
||||
-
|
||||
hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
|
||||
hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
|
||||
|
||||
- if (usbDeviceListAdd(list, usb) < 0) {
|
||||
- usbFreeDevice(usb);
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ } else if (!vendor && bus) {
|
||||
+ usb = usbFindDeviceByBus(bus, device);
|
||||
+ }
|
||||
+
|
||||
+ if (!usb)
|
||||
+ goto cleanup;
|
||||
|
||||
+ if (usbDeviceListAdd(list, usb) < 0) {
|
||||
+ usbFreeDevice(usb);
|
||||
+ goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
- /* Loop 2: Mark devices in temporary list as used by @name
|
||||
+ /* Mark devices in temporary list as used by @name
|
||||
* and add them do driver list. However, if something goes
|
||||
* wrong, perform rollback.
|
||||
*/
|
||||
- for (i = 0; i < usbDeviceListCount(list); i++) {
|
||||
- tmp = usbDeviceListGet(list, i);
|
||||
- usbDeviceSetUsedBy(tmp, name);
|
||||
+ if (qemuPrepareHostdevUSBDevices(driver, def->name, list) < 0)
|
||||
+ goto inactivedevs;
|
||||
|
||||
- VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs",
|
||||
- usbDeviceGetBus(tmp), usbDeviceGetDevno(tmp), name);
|
||||
- if (usbDeviceListAdd(driver->activeUsbHostdevs, tmp) < 0) {
|
||||
- usbFreeDevice(tmp);
|
||||
- goto inactivedevs;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Loop 3: Temporary list was successfully merged with
|
||||
+ /* Loop 2: Temporary list was successfully merged with
|
||||
* driver list, so steal all items to avoid freeing them
|
||||
* in cleanup label.
|
||||
*/
|
||||
@@ -675,13 +706,6 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int
|
||||
-qemuPrepareHostUSBDevices(struct qemud_driver *driver,
|
||||
- virDomainDefPtr def)
|
||||
-{
|
||||
- return qemuPrepareHostdevUSBDevices(driver, def->name, def->hostdevs, def->nhostdevs);
|
||||
-}
|
||||
-
|
||||
int qemuPrepareHostDevices(struct qemud_driver *driver,
|
||||
virDomainDefPtr def)
|
||||
{
|
||||
Index: libvirt-0.9.11.3/src/qemu/qemu_hostdev.h
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/qemu/qemu_hostdev.h
|
||||
+++ libvirt-0.9.11.3/src/qemu/qemu_hostdev.h
|
||||
@@ -38,8 +38,7 @@ int qemuPrepareHostdevPCIDevices(struct
|
||||
int nhostdevs);
|
||||
int qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
|
||||
const char *name,
|
||||
- virDomainHostdevDefPtr *hostdevs,
|
||||
- int nhostdevs);
|
||||
+ usbDeviceList *list);
|
||||
int qemuPrepareHostDevices(struct qemud_driver *driver,
|
||||
virDomainDefPtr def);
|
||||
void qemuReattachPciDevice(pciDevice *dev, struct qemud_driver *driver);
|
||||
Index: libvirt-0.9.11.3/src/qemu/qemu_hotplug.c
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/qemu/qemu_hotplug.c
|
||||
+++ libvirt-0.9.11.3/src/qemu/qemu_hotplug.c
|
||||
@@ -1116,11 +1116,13 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
-
|
||||
int qemuDomainAttachHostDevice(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainHostdevDefPtr hostdev)
|
||||
{
|
||||
+ usbDeviceList *list;
|
||||
+ usbDevice *usb = NULL;
|
||||
+
|
||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
|
||||
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("hostdev mode '%s' not supported"),
|
||||
@@ -1128,35 +1130,58 @@ int qemuDomainAttachHostDevice(struct qe
|
||||
return -1;
|
||||
}
|
||||
|
||||
- /* Resolve USB product/vendor to bus/device */
|
||||
- if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
|
||||
- hostdev->source.subsys.u.usb.vendor) {
|
||||
- usbDevice *usb;
|
||||
- usbDeviceList *list;
|
||||
-
|
||||
- if (qemuPrepareHostdevUSBDevices(driver, vm->def->name, &hostdev, 1) < 0)
|
||||
- goto error;
|
||||
+ if (!(list = usbDeviceListNew()))
|
||||
+ goto cleanup;
|
||||
|
||||
- list = usbFindDeviceByVendor(hostdev->source.subsys.u.usb.vendor,
|
||||
- hostdev->source.subsys.u.usb.product);
|
||||
+ if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
|
||||
+ 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;
|
||||
+
|
||||
+ if (vendor && bus) {
|
||||
+ usb = usbFindDevice(vendor, product, bus, device);
|
||||
+
|
||||
+ } else if (vendor && !bus) {
|
||||
+ usbDeviceList *devs = usbFindDeviceByVendor(vendor, product);
|
||||
+ if (!devs)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if (usbDeviceListCount(devs) > 1) {
|
||||
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||
+ _("multiple USB devices for %x:%x, "
|
||||
+ "use <address> to specify one"), vendor, product);
|
||||
+ usbDeviceListFree(devs);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ 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);
|
||||
+
|
||||
+ } else if (!vendor && bus) {
|
||||
+ usb = usbFindDeviceByBus(bus, device);
|
||||
+ }
|
||||
+
|
||||
+ if (!usb)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if (usbDeviceListAdd(list, usb) < 0) {
|
||||
+ usbFreeDevice(usb);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
- if (!list)
|
||||
- return -1;
|
||||
+ if (qemuPrepareHostdevUSBDevices(driver, vm->def->name, list) < 0)
|
||||
+ goto cleanup;
|
||||
|
||||
- usb = usbDeviceListGet(list, 0);
|
||||
usbDeviceListSteal(list, usb);
|
||||
- usbDeviceListFree(list);
|
||||
-
|
||||
- hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
|
||||
- hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
|
||||
-
|
||||
- usbFreeDevice(usb);
|
||||
}
|
||||
|
||||
-
|
||||
if (virSecurityManagerSetHostdevLabel(driver->securityManager,
|
||||
vm->def, hostdev) < 0)
|
||||
- return -1;
|
||||
+ goto cleanup;
|
||||
|
||||
switch (hostdev->source.subsys.type) {
|
||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
||||
@@ -1178,6 +1203,7 @@ int qemuDomainAttachHostDevice(struct qe
|
||||
goto error;
|
||||
}
|
||||
|
||||
+ usbDeviceListFree(list);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
@@ -1185,6 +1211,9 @@ error:
|
||||
vm->def, hostdev) < 0)
|
||||
VIR_WARN("Unable to restore host device labelling on hotplug fail");
|
||||
|
||||
+cleanup:
|
||||
+ usbDeviceListFree(list);
|
||||
+ usbDeviceListSteal(driver->activeUsbHostdevs, usb);
|
||||
return -1;
|
||||
}
|
||||
|
423
9914477e-usb-search-funcs.patch
Normal file
423
9914477e-usb-search-funcs.patch
Normal file
@ -0,0 +1,423 @@
|
||||
commit 9914477efc9764f691ca50faca6592a2d4fecec8
|
||||
Author: Guannan Ren <gren@redhat.com>
|
||||
Date: Fri May 4 15:49:58 2012 +0800
|
||||
|
||||
usb: create functions to search usb device accurately
|
||||
|
||||
usbFindDevice():get usb device according to
|
||||
idVendor, idProduct, bus, device
|
||||
it is the exact match of the four parameters
|
||||
|
||||
usbFindDeviceByBus():get usb device according to bus, device
|
||||
it returns only one usb device same as usbFindDevice
|
||||
|
||||
usbFindDeviceByVendor():get usb device according to idVendor,idProduct
|
||||
it probably returns multiple usb devices.
|
||||
|
||||
usbDeviceSearch(): a helper function to do the actual search
|
||||
|
||||
Index: libvirt-0.9.11.3/src/libvirt_private.syms
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/libvirt_private.syms
|
||||
+++ libvirt-0.9.11.3/src/libvirt_private.syms
|
||||
@@ -1084,6 +1084,8 @@ usbDeviceListNew;
|
||||
usbDeviceListSteal;
|
||||
usbDeviceSetUsedBy;
|
||||
usbFindDevice;
|
||||
+usbFindDeviceByBus;
|
||||
+usbFindDeviceByVendor;
|
||||
usbFreeDevice;
|
||||
usbGetDevice;
|
||||
|
||||
Index: libvirt-0.9.11.3/src/qemu/qemu_hostdev.c
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/qemu/qemu_hostdev.c
|
||||
+++ libvirt-0.9.11.3/src/qemu/qemu_hostdev.c
|
||||
@@ -594,13 +594,19 @@ qemuPrepareHostdevUSBDevices(struct qemu
|
||||
|
||||
/* Resolve a vendor/product to bus/device */
|
||||
if (hostdev->source.subsys.u.usb.vendor) {
|
||||
- usbDevice *usb
|
||||
- = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
|
||||
- hostdev->source.subsys.u.usb.product);
|
||||
+ usbDevice *usb;
|
||||
+ usbDeviceList *devs;
|
||||
|
||||
- if (!usb)
|
||||
+ devs = usbFindDeviceByVendor(hostdev->source.subsys.u.usb.vendor,
|
||||
+ hostdev->source.subsys.u.usb.product);
|
||||
+
|
||||
+ if (!devs)
|
||||
goto cleanup;
|
||||
|
||||
+ usb = usbDeviceListGet(devs, 0);
|
||||
+ usbDeviceListSteal(devs, usb);
|
||||
+ usbDeviceListFree(devs);
|
||||
+
|
||||
if ((tmp = usbDeviceListFind(driver->activeUsbHostdevs, usb))) {
|
||||
const char *other_name = usbDeviceGetUsedBy(tmp);
|
||||
|
||||
Index: libvirt-0.9.11.3/src/qemu/qemu_hotplug.c
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/qemu/qemu_hotplug.c
|
||||
+++ libvirt-0.9.11.3/src/qemu/qemu_hotplug.c
|
||||
@@ -1131,16 +1131,22 @@ int qemuDomainAttachHostDevice(struct qe
|
||||
/* Resolve USB product/vendor to bus/device */
|
||||
if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
|
||||
hostdev->source.subsys.u.usb.vendor) {
|
||||
+ usbDevice *usb;
|
||||
+ usbDeviceList *list;
|
||||
+
|
||||
if (qemuPrepareHostdevUSBDevices(driver, vm->def->name, &hostdev, 1) < 0)
|
||||
goto error;
|
||||
|
||||
- usbDevice *usb
|
||||
- = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
|
||||
- hostdev->source.subsys.u.usb.product);
|
||||
+ list = usbFindDeviceByVendor(hostdev->source.subsys.u.usb.vendor,
|
||||
+ hostdev->source.subsys.u.usb.product);
|
||||
|
||||
- if (!usb)
|
||||
+ if (!list)
|
||||
return -1;
|
||||
|
||||
+ usb = usbDeviceListGet(list, 0);
|
||||
+ usbDeviceListSteal(list, usb);
|
||||
+ usbDeviceListFree(list);
|
||||
+
|
||||
hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
|
||||
hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
|
||||
|
||||
Index: libvirt-0.9.11.3/src/util/hostusb.c
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/util/hostusb.c
|
||||
+++ libvirt-0.9.11.3/src/util/hostusb.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright (C) 2009-2011 Red Hat, Inc.
|
||||
+ * Copyright (C) 2009-2012 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -42,9 +42,16 @@
|
||||
#define USB_ID_LEN 10 /* "1234 5678" */
|
||||
#define USB_ADDR_LEN 8 /* "123:456" */
|
||||
|
||||
+/* For virReportOOMError() and virReportSystemError() */
|
||||
+#define VIR_FROM_THIS VIR_FROM_NONE
|
||||
+
|
||||
+#define usbReportError(code, ...) \
|
||||
+ virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \
|
||||
+ __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
+
|
||||
struct _usbDevice {
|
||||
- unsigned bus;
|
||||
- unsigned dev;
|
||||
+ unsigned int bus;
|
||||
+ unsigned int dev;
|
||||
|
||||
char name[USB_ADDR_LEN]; /* domain:bus:slot.function */
|
||||
char id[USB_ID_LEN]; /* product vendor */
|
||||
@@ -57,15 +64,14 @@ struct _usbDeviceList {
|
||||
usbDevice **devs;
|
||||
};
|
||||
|
||||
-/* For virReportOOMError() and virReportSystemError() */
|
||||
-#define VIR_FROM_THIS VIR_FROM_NONE
|
||||
-
|
||||
-#define usbReportError(code, ...) \
|
||||
- virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \
|
||||
- __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
+typedef enum {
|
||||
+ USB_DEVICE_ALL = 0,
|
||||
+ USB_DEVICE_FIND_BY_VENDOR = 1 << 0,
|
||||
+ USB_DEVICE_FIND_BY_BUS = 1 << 1,
|
||||
+} usbDeviceFindFlags;
|
||||
|
||||
static int usbSysReadFile(const char *f_name, const char *d_name,
|
||||
- int base, unsigned *value)
|
||||
+ int base, unsigned int *value)
|
||||
{
|
||||
int ret = -1, tmp;
|
||||
char *buf = NULL;
|
||||
@@ -94,13 +100,22 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int usbFindBusByVendor(unsigned vendor, unsigned product,
|
||||
- unsigned *bus, unsigned *devno)
|
||||
+static usbDeviceList *
|
||||
+usbDeviceSearch(unsigned int vendor,
|
||||
+ unsigned int product,
|
||||
+ unsigned int bus,
|
||||
+ unsigned int devno,
|
||||
+ unsigned int flags)
|
||||
{
|
||||
DIR *dir = NULL;
|
||||
- int ret = -1, found = 0;
|
||||
+ bool found = false;
|
||||
char *ignore = NULL;
|
||||
struct dirent *de;
|
||||
+ usbDeviceList *list = NULL, *ret = NULL;
|
||||
+ usbDevice *usb;
|
||||
+
|
||||
+ if (!(list = usbDeviceListNew()))
|
||||
+ goto cleanup;
|
||||
|
||||
dir = opendir(USB_SYSFS "/devices");
|
||||
if (!dir) {
|
||||
@@ -111,61 +126,145 @@ static int usbFindBusByVendor(unsigned v
|
||||
}
|
||||
|
||||
while ((de = readdir(dir))) {
|
||||
- unsigned found_prod, found_vend;
|
||||
+ unsigned int found_prod, found_vend, found_bus, found_devno;
|
||||
+ char *tmpstr = de->d_name;
|
||||
+
|
||||
if (de->d_name[0] == '.' || strchr(de->d_name, ':'))
|
||||
continue;
|
||||
|
||||
if (usbSysReadFile("idVendor", de->d_name,
|
||||
16, &found_vend) < 0)
|
||||
goto cleanup;
|
||||
+
|
||||
if (usbSysReadFile("idProduct", de->d_name,
|
||||
16, &found_prod) < 0)
|
||||
goto cleanup;
|
||||
|
||||
- if (found_prod == product && found_vend == vendor) {
|
||||
- /* Lookup bus.addr info */
|
||||
- char *tmpstr = de->d_name;
|
||||
- unsigned found_bus, found_addr;
|
||||
-
|
||||
- if (STRPREFIX(de->d_name, "usb"))
|
||||
- tmpstr += 3;
|
||||
-
|
||||
- if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
|
||||
- usbReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
- _("Failed to parse dir name '%s'"),
|
||||
- de->d_name);
|
||||
- goto cleanup;
|
||||
- }
|
||||
-
|
||||
- if (usbSysReadFile("devnum", de->d_name,
|
||||
- 10, &found_addr) < 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- *bus = found_bus;
|
||||
- *devno = found_addr;
|
||||
- found = 1;
|
||||
- break;
|
||||
+ if (STRPREFIX(de->d_name, "usb"))
|
||||
+ tmpstr += 3;
|
||||
+
|
||||
+ if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
|
||||
+ usbReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("Failed to parse dir name '%s'"),
|
||||
+ de->d_name);
|
||||
+ goto cleanup;
|
||||
}
|
||||
- }
|
||||
|
||||
- if (!found)
|
||||
- usbReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
- _("Did not find USB device %x:%x"), vendor, product);
|
||||
- else
|
||||
- ret = 0;
|
||||
+ if (usbSysReadFile("devnum", de->d_name,
|
||||
+ 10, &found_devno) < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if ((flags & USB_DEVICE_FIND_BY_VENDOR) &&
|
||||
+ (found_prod != product || found_vend != vendor))
|
||||
+ continue;
|
||||
+
|
||||
+ if (flags & USB_DEVICE_FIND_BY_BUS) {
|
||||
+ if (found_bus != bus || found_devno != devno)
|
||||
+ continue;
|
||||
+ found = true;
|
||||
+ }
|
||||
+
|
||||
+ usb = usbGetDevice(found_bus, found_devno);
|
||||
+ if (!usb)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if (usbDeviceListAdd(list, usb) < 0) {
|
||||
+ usbFreeDevice(usb);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ if (found)
|
||||
+ break;
|
||||
+ }
|
||||
+ ret = list;
|
||||
|
||||
cleanup:
|
||||
if (dir) {
|
||||
int saved_errno = errno;
|
||||
- closedir (dir);
|
||||
+ closedir(dir);
|
||||
errno = saved_errno;
|
||||
}
|
||||
+
|
||||
+ if (!ret)
|
||||
+ usbDeviceListFree(list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+usbDeviceList *
|
||||
+usbFindDeviceByVendor(unsigned int vendor, unsigned product)
|
||||
+{
|
||||
+
|
||||
+ usbDeviceList *list;
|
||||
+ if (!(list = usbDeviceSearch(vendor, product, 0 , 0,
|
||||
+ USB_DEVICE_FIND_BY_VENDOR)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (list->count == 0) {
|
||||
+ usbReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("Did not find USB device %x:%x"), vendor, product);
|
||||
+ usbDeviceListFree(list);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return list;
|
||||
+}
|
||||
+
|
||||
usbDevice *
|
||||
-usbGetDevice(unsigned bus,
|
||||
- unsigned devno)
|
||||
+usbFindDeviceByBus(unsigned int bus, unsigned devno)
|
||||
+{
|
||||
+ usbDevice *usb;
|
||||
+ usbDeviceList *list;
|
||||
+
|
||||
+ if (!(list = usbDeviceSearch(0, 0, bus, devno,
|
||||
+ USB_DEVICE_FIND_BY_BUS)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (list->count == 0) {
|
||||
+ usbReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("Did not find USB device bus:%u device:%u"),
|
||||
+ bus, devno);
|
||||
+ usbDeviceListFree(list);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ usb = usbDeviceListGet(list, 0);
|
||||
+ usbDeviceListSteal(list, usb);
|
||||
+ usbDeviceListFree(list);
|
||||
+
|
||||
+ return usb;
|
||||
+}
|
||||
+
|
||||
+usbDevice *
|
||||
+usbFindDevice(unsigned int vendor,
|
||||
+ unsigned int product,
|
||||
+ unsigned int bus,
|
||||
+ unsigned int devno)
|
||||
+{
|
||||
+ 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;
|
||||
+
|
||||
+ if (list->count == 0) {
|
||||
+ usbReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("Did not find USB device %x:%x bus:%u device:%u"),
|
||||
+ vendor, product, bus, devno);
|
||||
+ usbDeviceListFree(list);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ usb = usbDeviceListGet(list, 0);
|
||||
+ usbDeviceListSteal(list, usb);
|
||||
+ usbDeviceListFree(list);
|
||||
+
|
||||
+ return usb;
|
||||
+}
|
||||
+
|
||||
+usbDevice *
|
||||
+usbGetDevice(unsigned int bus,
|
||||
+ unsigned int devno)
|
||||
{
|
||||
usbDevice *dev;
|
||||
|
||||
@@ -207,21 +306,6 @@ usbGetDevice(unsigned bus,
|
||||
return dev;
|
||||
}
|
||||
|
||||
-
|
||||
-usbDevice *
|
||||
-usbFindDevice(unsigned vendor,
|
||||
- unsigned product)
|
||||
-{
|
||||
- unsigned bus = 0, devno = 0;
|
||||
-
|
||||
- if (usbFindBusByVendor(vendor, product, &bus, &devno) < 0) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- return usbGetDevice(bus, devno);
|
||||
-}
|
||||
-
|
||||
-
|
||||
void
|
||||
usbFreeDevice(usbDevice *dev)
|
||||
{
|
||||
@@ -247,13 +331,13 @@ const char *usbDeviceGetName(usbDevice *
|
||||
return dev->name;
|
||||
}
|
||||
|
||||
-unsigned usbDeviceGetBus(usbDevice *dev)
|
||||
+unsigned int usbDeviceGetBus(usbDevice *dev)
|
||||
{
|
||||
return dev->bus;
|
||||
}
|
||||
|
||||
|
||||
-unsigned usbDeviceGetDevno(usbDevice *dev)
|
||||
+unsigned int usbDeviceGetDevno(usbDevice *dev)
|
||||
{
|
||||
return dev->dev;
|
||||
}
|
||||
Index: libvirt-0.9.11.3/src/util/hostusb.h
|
||||
===================================================================
|
||||
--- libvirt-0.9.11.3.orig/src/util/hostusb.h
|
||||
+++ libvirt-0.9.11.3/src/util/hostusb.h
|
||||
@@ -28,17 +28,27 @@
|
||||
typedef struct _usbDevice usbDevice;
|
||||
typedef struct _usbDeviceList usbDeviceList;
|
||||
|
||||
-usbDevice *usbGetDevice(unsigned bus,
|
||||
- unsigned devno);
|
||||
-usbDevice *usbFindDevice(unsigned vendor,
|
||||
- unsigned product);
|
||||
+usbDevice *usbGetDevice(unsigned int bus,
|
||||
+ unsigned int devno);
|
||||
+
|
||||
+usbDevice *usbFindDeviceByBus(unsigned int bus,
|
||||
+ unsigned int devno);
|
||||
+
|
||||
+usbDeviceList *usbFindDeviceByVendor(unsigned int vendor,
|
||||
+ unsigned int product);
|
||||
+
|
||||
+usbDevice *usbFindDevice(unsigned int vendor,
|
||||
+ unsigned int product,
|
||||
+ unsigned int bus,
|
||||
+ unsigned int devno);
|
||||
+
|
||||
void usbFreeDevice (usbDevice *dev);
|
||||
void usbDeviceSetUsedBy(usbDevice *dev, const char *name);
|
||||
const char *usbDeviceGetUsedBy(usbDevice *dev);
|
||||
const char *usbDeviceGetName(usbDevice *dev);
|
||||
|
||||
-unsigned usbDeviceGetBus(usbDevice *dev);
|
||||
-unsigned usbDeviceGetDevno(usbDevice *dev);
|
||||
+unsigned int usbDeviceGetBus(usbDevice *dev);
|
||||
+unsigned int usbDeviceGetDevno(usbDevice *dev);
|
||||
|
||||
/*
|
||||
* Callback that will be invoked once for each file
|
@ -1,3 +1,12 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Jun 12 14:18:23 MDT 2012 - jfehlig@suse.com
|
||||
|
||||
- VUL-1: Fix hotplug support for usb devices with same vendorID,
|
||||
productID
|
||||
9914477e-usb-search-funcs.patch
|
||||
05abd150-usb-improve-hotplug.patch
|
||||
bnc#766559
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed May 30 16:00:38 MDT 2012 - jfehlig@suse.com
|
||||
|
||||
|
@ -410,6 +410,8 @@ Source1: libvirtd.init
|
||||
Source2: libvirtd-relocation-server.fw
|
||||
Source99: baselibs.conf
|
||||
# Upstream patches
|
||||
Patch0: 9914477e-usb-search-funcs.patch
|
||||
Patch1: 05abd150-usb-improve-hotplug.patch
|
||||
# Need to go upstream
|
||||
Patch100: xen-name-for-devid.patch
|
||||
Patch101: clone.patch
|
||||
@ -545,6 +547,8 @@ Authors:
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch0 -p1
|
||||
%patch1 -p1
|
||||
%patch100 -p1
|
||||
%patch101
|
||||
%patch102 -p1
|
||||
|
Loading…
Reference in New Issue
Block a user