]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Use .hostdevice attribute for usb-host
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 9 Sep 2020 11:15:15 +0000 (13:15 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 1 Oct 2020 08:59:35 +0000 (10:59 +0200)
This originally started as bug 1595525 in which namespaces and
libusb used in QEMU were not playing nicely with each other. The
problem was that libusb built a cache of USB devices it saw
(which was a very limited set because of the namespace) and then
expected to receive udev events to keep the cache in sync. But
those udev events didn't come because on hotplug when we mknod()
devices in the namespace no udev event is generated. And what is
worse - libusb failed to open a device that wasn't in the cache.

Without going further into what the problem was, libusb added a
new API for opening USB devices that avoids using cache which
QEMU incorporated and exposes under "hostdevice" attribute.

What is even nicer is that QEMU uses qemu_open() for path
provided in the attribute and thus FD passing could be used.
Except qemu_open() expects so called FD sets instead of `getfd'
and these are not implemented in libvirt, yet.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1877218
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_command.c

index 91b59538aaa13465f46ed6de8db14146368ce76b..f7e7236dff456ac0d000866de7c81e44fc940438 100644 (file)
@@ -4461,16 +4461,21 @@ qemuBuildUSBHostdevDevStr(const virDomainDef *def,
     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
     virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
 
-    if (!dev->missing && !usbsrc->bus && !usbsrc->device) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("USB host device is missing bus/device information"));
-        return NULL;
-    }
-
     virBufferAddLit(&buf, "usb-host");
     if (!dev->missing) {
-        virBufferAsprintf(&buf, ",hostbus=%d,hostaddr=%d",
-                          usbsrc->bus, usbsrc->device);
+        if (usbsrc->bus == 0 && usbsrc->device == 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("USB host device is missing bus/device information"));
+            return NULL;
+        }
+
+        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_HOST_HOSTDEVICE)) {
+            virBufferAsprintf(&buf, ",hostdevice=/dev/bus/usb/%03d/%03d",
+                              usbsrc->bus, usbsrc->device);
+        } else {
+            virBufferAsprintf(&buf, ",hostbus=%d,hostaddr=%d",
+                              usbsrc->bus, usbsrc->device);
+        }
     }
     virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
     if (dev->info->bootIndex)