From: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
To: svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com, den@openvz.org
Subject: [QEMU HCI-8.0 PATCH v2 04/13] usb-host: preserve hostdev FD during CPR migration #VSTOR-137800
Date: Fri, 4 Sep 2026 22:04:34 +0300 [thread overview]
Message-ID: <20260904190443.795902-5-andrey.drobyshev@virtuozzo.com> (raw)
In-Reply-To: <20260904190443.795902-1-andrey.drobyshev@virtuozzo.com>
In .realize(), save freshly opened host device FD into the CPR registry,
and then reuse it on CPR target. Also, add deletion of that FD from
registry to usb_host_open() / usb_host_close() cleanup paths.
For this to work, we also need to skip the .post-load() code which
closes, detaches the device, and then rescans the host bus to reopen
matching hostdevs. For the CPR-case migration we don't want any of that
as the hostdev FD stays preserved, and the guest shouldn't notice the
switchover.
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
hw/usb/host-libusb.c | 53 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 86f96087085..eaacfd34c54 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -47,6 +47,7 @@
#include "qapi/error.h"
#include "migration/blocker.h"
+#include "migration/cpr.h"
#include "migration/vmstate.h"
#include "monitor/monitor.h"
#include "qemu/error-report.h"
@@ -947,6 +948,38 @@ static void usb_host_ep_update(USBHostDevice *s)
libusb_free_config_descriptor(conf);
}
+static char *usb_host_cpr_fd_name(USBHostDevice *s)
+{
+ /*
+ * Prefix the CPR fd registry key so it can't collide with a chardev
+ * label or netdev id in the same flat namespace.
+ */
+ return DEVICE(s)->id ?
+ g_strdup_printf("usb-host/%s", DEVICE(s)->id) : NULL;
+}
+
+static int usb_host_cpr_find_fd(USBHostDevice *s)
+{
+ g_autofree char *name = usb_host_cpr_fd_name(s);
+ return name ? cpr_find_fd(name, 0) : -1;
+}
+
+static void usb_host_cpr_save_fd(USBHostDevice *s, int fd)
+{
+ g_autofree char *name = usb_host_cpr_fd_name(s);
+ if (name) {
+ cpr_save_fd(name, 0, fd);
+ }
+}
+
+static void usb_host_cpr_delete_fd(USBHostDevice *s)
+{
+ g_autofree char *name = usb_host_cpr_fd_name(s);
+ if (name) {
+ cpr_delete_fd(name, 0);
+ }
+}
+
static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
{
USBDevice *udev = USB_DEVICE(s);
@@ -1069,6 +1102,7 @@ fail:
s->dev = NULL;
}
if (s->hostfd != -1) {
+ usb_host_cpr_delete_fd(s);
close(s->hostfd);
s->hostfd = -1;
}
@@ -1130,6 +1164,7 @@ static int usb_host_close(USBHostDevice *s)
s->dev = NULL;
if (s->hostfd != -1) {
+ usb_host_cpr_delete_fd(s);
close(s->hostfd);
s->hostfd = -1;
}
@@ -1218,9 +1253,13 @@ static void usb_host_realize(USBDevice *udev, Error **errp)
if (s->hostdevice) {
int fd;
s->needs_autoscan = false;
- fd = qemu_open(s->hostdevice, O_RDWR, errp);
+ fd = usb_host_cpr_find_fd(s);
if (fd < 0) {
- return;
+ fd = qemu_open(s->hostdevice, O_RDWR, errp);
+ if (fd < 0) {
+ return;
+ }
+ usb_host_cpr_save_fd(s, fd);
}
rc = usb_host_open(s, NULL, fd);
if (rc < 0) {
@@ -1757,6 +1796,16 @@ static int usb_host_post_load(void *opaque, int version_id)
{
USBHostDevice *dev = opaque;
+ /*
+ * For CPR migration, device wasn't released/reset, and the guest
+ * is unaware of the switchover. The detach/rescan performed in
+ * usb_host_post_load_bh() only exists for cross-host migration.
+ * Skip it for CPR.
+ */
+ if (cpr_is_incoming()) {
+ return 0;
+ }
+
if (!dev->bh_postld) {
dev->bh_postld = qemu_bh_new_guarded(usb_host_post_load_bh, dev,
&DEVICE(dev)->mem_reentrancy_guard);
--
2.47.1
next prev parent reply other threads:[~2026-09-04 19:04 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 19:04 [QEMU HCI-8.0 PATCH v2 00/13] usb-host: support CPR migration Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 01/13] migration/cpr: fix use-after-free in cpr_delete_fd() Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 02/13] usb-host: don't leak hostdev FD on open failure #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 03/13] usb-host: add migration blocker for CPR modes #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` Andrey Drobyshev [this message]
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 05/13] usb-host: factor out usb_host_reap_xfers() #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 06/13] usb-host: drain in-flight URBs across CPR #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 07/13] usb-host: re-issue drained URBs if CPR is aborted #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 08/13] usb-host: skip product-string read on CPR incoming #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 09/13] usb-host: hand off the device across cpr-transfer #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 10/13] usb: migrate the interface altsetting #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 11/13] usb-host: reconfigure endpoints on CPR incoming #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 12/13] hcd-xhci: resync isochronous endpoints after CPR #VSTOR-137800 Andrey Drobyshev
2026-09-04 19:04 ` [QEMU HCI-8.0 PATCH v2 13/13] usb-host: make CPR migration blocker conditional #VSTOR-137800 Andrey Drobyshev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260904190443.795902-5-andrey.drobyshev@virtuozzo.com \
--to=andrey.drobyshev@virtuozzo.com \
--cc=den@openvz.org \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox