On Mon, Mar 26, 2012 at 17:40:00 +0200, Michal Privoznik wrote:
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 qemuProcessReconnect() as well.
^^
qemuProcessStop()
---
src/qemu/qemu_hostdev.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index d4d7461..6ce2421 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -755,6 +755,64 @@ 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);
This is the last usage of usb so I think it's better to call
usbFreeDevice(usb); here to avoid having to call it several times later.
+ 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);
+ usbFreeDevice(usb);
Now, the above line may be removed.
+ 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);
+ }
+
+ usbFreeDevice(usb);
And this one as well.
+ }
+}
void qemuDomainReAttachHostDevices(struct qemud_driver *driver,
virDomainDefPtr def)
@@ -764,4 +822,7 @@ void qemuDomainReAttachHostDevices(struct qemud_driver *driver,
qemuDomainReAttachHostdevDevices(driver, def->name, def->hostdevs,
def->nhostdevs);
+
+ qemuDomainReAttachHostUsbDevices(driver, def->name, def->hostdevs,
+ def->nhostdevs);
}
ACK
Jirka