From e2f5dd6134ebeb6846450c7d7782273d3d274859 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Mon, 26 Mar 2012 16:40:01 +0200 Subject: [PATCH] qemu: Delete USB devices used by domain on stop To prevent assigning one USB device to two domains, we keep a list of assigned USB devices. On domain startup - qemuProcessStart() - we insert devices used by domain into the list but remove them only on detach-device. Devices are, however, released on qemuProcessStop() as well. --- src/qemu/qemu_hostdev.c | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index d4d746162c..a8890ebfa7 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -755,6 +755,63 @@ void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver, pciDeviceListFree(pcidevs); } +static void +qemuDomainReAttachHostUsbDevices(struct qemud_driver *driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + int i; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + usbDevice *usb, *tmp; + const char *used_by = NULL; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + + usb = usbGetDevice(hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device); + + if (!usb) { + VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + name); + continue; + } + + /* Delete only those USB devices which belongs + * to domain @name because qemuProcessStart() might + * have failed because USB device is already taken. + * Therefore we want to steal only those devices from + * the list which were taken by @name */ + + tmp = usbDeviceListFind(driver->activeUsbHostdevs, usb); + usbFreeDevice(usb); + + if (!tmp) { + VIR_WARN("Unable to find device %03d.%03d " + "in list of active USB devices", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device); + continue; + } + + used_by = usbDeviceGetUsedBy(tmp); + if (STREQ_NULLABLE(used_by, name)) { + VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + name); + + usbDeviceListDel(driver->activeUsbHostdevs, tmp); + } + } +} void qemuDomainReAttachHostDevices(struct qemud_driver *driver, virDomainDefPtr def) @@ -764,4 +821,7 @@ void qemuDomainReAttachHostDevices(struct qemud_driver *driver, qemuDomainReAttachHostdevDevices(driver, def->name, def->hostdevs, def->nhostdevs); + + qemuDomainReAttachHostUsbDevices(driver, def->name, def->hostdevs, + def->nhostdevs); } -- GitLab