[libvirt] [PATCH v2 2/3] qemu: make use of usb search function to initialize usb devices
Martin Kletzander
mkletzan at redhat.com
Wed May 2 15:11:11 UTC 2012
On 05/01/2012 10:16 AM, Guannan Ren wrote:
> 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_hostdev.c | 118 ++++++++++++++++++++++++++++++-----------------
> src/qemu/qemu_hostdev.h | 3 +-
> 2 files changed, 76 insertions(+), 45 deletions(-)
>
> diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
> index 8594fb2..a3d4ad4 100644
> --- a/src/qemu/qemu_hostdev.c
> +++ b/src/qemu/qemu_hostdev.c
> @@ -565,13 +565,51 @@ qemuPrepareHostPCIDevices(struct qemud_driver *driver,
> int
> qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
> const char *name,
> - virDomainHostdevDefPtr *hostdevs,
> - int nhostdevs)
> + usbDeviceList *list)
> {
> - int ret = -1;
> int i;
> + usbDevice *tmp;
> +
> + for (i = 0; i < usbDeviceListCount(list); 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 the list of usb
> + * 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,64 +624,65 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
> */
> 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
> - = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
> - hostdev->source.subsys.u.usb.product);
> + 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);
> if (!usb)
> goto cleanup;
>
> - 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);
> + } else if (vendor && !bus) {
> + usbDeviceList *devs = usbFindDevByVendor(vendor, product);
> + if (!devs)
> + goto cleanup;
> +
> + if (usbDeviceListCount(devs) > 1) {
> + qemuReportError(VIR_ERR_XML_ERROR,
> + _("multiple USB deivces %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);
>
> - if (usbDeviceListAdd(list, usb) < 0) {
> - usbFreeDevice(usb);
> + } else if (!vendor && bus) {
> + usb = usbFindDevByBus(bus, device);
> + if (!usb)
> goto cleanup;
> - }
> + }
>
> + 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.
> */
> @@ -669,13 +708,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)
> {
> diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h
> index 371630a..a8acccf 100644
> --- a/src/qemu/qemu_hostdev.h
> +++ b/src/qemu/qemu_hostdev.h
> @@ -38,8 +38,7 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
> 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);
This looks good also, ACK.
Martin
More information about the libvir-list
mailing list