From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from PA4PR04CU001.outbound.protection.outlook.com (mail-francecentralazon11023105.outbound.protection.outlook.com [40.107.162.105]) by lore.virtuozzo.com (Postfix) with ESMTPS id 31743802A5 for ; Tue, 6 Oct 2026 16:50:28 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=qyQjkVfVAvlNkue4Z/93yCGgDQ1RO3a2764SfCRfEqVn0FwmMGJkH45Gxfp24iRpCUtSIDwwqOpbbPRQsSYVJ5bmMzeMAHUemXh3QGiRGhGLaCrZh5aqb5bDP92GU8RABoj7ZwPAU0o56HfbHWkq9k/lVbFmanU+NXfIsyEvINNoxKU8zcIC2UWyltmmfd6DB1J56zvHsw1Dr3vSNH5/D+FJVWyY2ZUW0G51X4GB8jey8O+oN7x43wNtqUM9H01Z5NMtaGrxMt+YHxWaKvip1WnG+XQX4u5fQpWz5wjnb2SSt/cC5nOcYV+/UGlAc4IxX3nJks3u1rwNZS9MZkk9Zw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=uYpPXXQxbFWhK1PVyjhrLyArApwt6hQbIrf7tiLQxo8=; b=IvVdv9Ae+ipF+l7epwk5OKtNHmgwNR0hC+mM4sv04QCjS1SFGrsoGgq3A2UsfOEwqng3s86GzS9zdeRJ5cE7x/+PAYPxWmeAbwiNYCwwpk4v1aq3htfv4r7ycd7uExiwkstiij0JSkCqDoMkTiU9FOjUFpvS6OHhBCtPvxPJt5b2cXWMxqGb45AS++eqSfziw1gr/oNgsRKGG6M+wedcKYV4+QXFA5XeiN3MUcIYCXT0+eJ3bi9tJD0K7UUJaFnjutRVafto+v1cTQTAF+QrbvtLtxqiTvccZiaqqjX+ZTGVZWgQLL0kxKg26mY1JJC2b7q7PW1G6u35lf0IqQ5LZw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 69.169.224.2) smtp.rcpttodomain=virtuozzo.com smtp.mailfrom=eu-central-1.amazonses.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=sashiko.virtuozzo.com; dkim=pass (signature was verified) header.d=sashiko.virtuozzo.com; dkim=pass (signature was verified) header.d=amazonses.com; arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.onmicrosoft.com; s=selector2-virtuozzo-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=uYpPXXQxbFWhK1PVyjhrLyArApwt6hQbIrf7tiLQxo8=; b=gAkGNGyX7LgXT6Sq2F1so8V4ojB2wbjFpCSr0dTcokHaceaF87yLWKVbBq3XwwiurhENnX4cWqA7GR9IFQA62I9t1k8vKywQgogJa/VO05lc55DxomI6esiiV0oyMmrrasRjpW4yy03RlExzT0Al898CLw90gVTFoHMrHDIinow= Received: from DU2P251CA0027.EURP251.PROD.OUTLOOK.COM (2603:10a6:10:230::33) by DB9PR08MB8228.eurprd08.prod.outlook.com (2603:10a6:10:37f::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.472.18; Tue, 6 Oct 2026 16:50:24 +0000 Received: from DU2PEPF00028CFE.eurprd03.prod.outlook.com (2603:10a6:10:230:cafe::20) by DU2P251CA0027.outlook.office365.com (2603:10a6:10:230::33) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.472.20 via Frontend Transport; Tue, 6 Oct 2026 16:50:24 +0000 Authentication-Results: mx.microsoft.com 1; spf=pass (sender IP is 69.169.224.2) smtp.mailfrom=eu-central-1.amazonses.com; dkim=pass (signature was verified) header.d=sashiko.virtuozzo.com;dkim=pass (signature was verified) header.d=amazonses.com;dmarc=pass action=none header.from=sashiko.virtuozzo.com; Received-SPF: Pass (protection.outlook.com: domain of eu-central-1.amazonses.com designates 69.169.224.2 as permitted sender) receiver=protection.outlook.com; client-ip=69.169.224.2; helo=b224-2.smtp-out.eu-central-1.amazonses.com; pr=C Received: from b224-2.smtp-out.eu-central-1.amazonses.com (69.169.224.2) by DU2PEPF00028CFE.mail.protection.outlook.com (10.167.242.182) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.472.14 via Frontend Transport; Tue, 6 Oct 2026 16:50:24 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=23yjbh4k34hwzfubhuiim7m4inbd3ick; d=sashiko.virtuozzo.com; t=1791305423; h=From:Subject:To:Cc:In-Reply-To:References:Content-Type:Content-Transfer-Encoding:Date:Message-ID; bh=e1TXfmbPZqyhuNZYXN2/LNrSurtqii7BLd/9ill1qFA=; b=rj84NCZfcNgleve75dtFvfJdVglmtrxFebgCWmBUfHmBUK7ltfDDFZGk+iDj+SaH 3BUBdA3hCTHSlusNpESzr2t8J+ldsLZdNsB6Xzi1UiItFylk7xdcZyWTurykpSbLERe t1MO1i3g9KsJfvMJMiIddu1tDxLXMZjjeRk2QBybUhqLMJizfV/xUGxGdqka34C1cpp PsjOSRM308qXZVPOLyUOiwhVo1NKhPzfwiDSSXT1O8jNXpgDt4qDrUUU1n8jN7lkBey AomnF2ORx7PxifqYMLisvnzMmvSH9alnNJipOd9jGt6RbUxVTtbbOP29K9ihQdHf/Mf ylDIPtjj3Q== DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=sokbgaaqhfgd6qjht2wmdajpuuanpimv; d=amazonses.com; t=1791305423; h=From:Subject:To:Cc:In-Reply-To:References:Content-Type:Content-Transfer-Encoding:Date:Message-ID:Feedback-ID; bh=e1TXfmbPZqyhuNZYXN2/LNrSurtqii7BLd/9ill1qFA=; b=N/TUqpG4FVBGzqudv2ybRRQfbN8b0/BqarAMSNHQfA19uXll1bfVGlMLGgmJYDyG krnBL2LdZdMKfCkQieFa5/phAVDxLGB/+X9KVN9baZdP5PGlCrGFFOPTc0wNrXKgLPp pCueLWPTesLlMeubd3U2WX7x1r1fOj9gEBNyHcpg= From: no-reply@sashiko.virtuozzo.com Subject: Re: [PATCH QEMU HCI-8.0 v8 10/14] usb-host: hand off the device across cpr-transfer #VSTOR-137800 To: Andrey Drobyshev , svt-core@virtuozzo.com Cc: den@openvz.org, andrey.drobyshev@virtuozzo.com In-Reply-To: <20261006-usb-host_v3-v8-10-72ae4fb8977b@virtuozzo.com> References: <20261006-usb-host_v3-v8-0-72ae4fb8977b@virtuozzo.com> <20261006-usb-host_v3-v8-10-72ae4fb8977b@virtuozzo.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Date: Tue, 6 Oct 2026 16:50:23 +0000 Message-ID: <010701a1121f9b92-d5e081d5-228f-46b8-8670-b6eee5a110ea-000000@eu-central-1.amazonses.com> Feedback-ID: ::1.eu-central-1.2wRQJBpg9g1fGRYexx3dUuYGS25Bux+2TEOx72/m6U4=:AmazonSES X-SES-Outgoing: 2026.10.06-69.169.224.2 X-EOPAttributedMessage: 0 X-EOPTenantAttributedMessage: 0bc7f26d-0264-416e-a6fc-8352af79c58f:0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF00028CFE:EE_|DB9PR08MB8228:EE_ MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: f0399b97-4508-46af-9f4f-08df23c9eac4 X-LD-Processed: 0bc7f26d-0264-416e-a6fc-8352af79c58f,ExtAddr X-MS-Exchange-AtpMessageProperties: SA List-Id: svt-core@virtuozzo.com X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|704161411799003|61400799027|376014|32142699015|9140799003|48200799018|22082099003|10067099003|5063699009|56012099006|18002099003|16102099003|5113699003|4143699003|55112099003|4113699003|13003099007; X-Microsoft-Antispam-Message-Info: m7ugiHKaT0OOSwvyPlaM4FEfiUMzwCHlE0zLg7wUIIs3djZa+leEB49Btgr3M5sCVF9VEeCOGflEFYINHFBn4iNh3vpuFEIucEjr6Owgo/IcYhn+9AEaRWYlfnalsb0nRpJM7Gpj1S1aAWoFtMmQ2jXVYaD/aahcQM9raevT8OpLEYAdXUCsIArIJEG8zp7Q3YStp2CUi1MA3781g/aU2lk8liM2kaf1U3Y3B5dd985D2I90YxoknnZKnARGIl+Cusxi40tHi+NMrz3chAx5UnvfEaoJgkocF7DBMzgzLuRwD1KzxDb0IHBz49DoMgNdXLsGApvk+Efk2+e3jqtHjX4WlRfhJfjRrYV1ak4kw3cyKO5se8BrZ/wYEFpTaQU4hOfqJ09DePPUGN8xXw2AG434PnPIXW0B7FNQSAhFvRj1RKIsT0EBdCScFmwXSnW4ahmEQLCc4s64HdzCA40CVTjeXl9Chp4ISN7fK0b1DzF1dDjsjUFty45VIT+UswNWKxEIF8/S3g2Emjbz9IF1DnKbSOUu5DN4fe8KPmXc/AP6V6ASdnGdKMeb51/VxTz30puwGD19bZhH2G5JYnML2IVU/GNB/R/seZdPMIinhdrKdjSvprk945yfP4cgEIAx981dxIWQPHk+IWyQZD5u0RWYLUEIZ3y9p0a/x2sDrdWNJuignz1ey17egGsuygb6WR6Rza5XF5CPiCMArXlFjMIOYDQ8pvImmviA1ClqA4aN6kasyUfvlHBPXeJYoQWy2WJpvNq+totq4s1Ttn7q7Fyr/MTkhtGwY1vi1g27NWvjodY7A+5slT9dNMhRHPFu X-Forefront-Antispam-Report: CIP:69.169.224.2;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:b224-2.smtp-out.eu-central-1.amazonses.com;PTR:b224-2.smtp-out.eu-central-1.amazonses.com;CAT:NONE;SFS:(13230040)(704161411799003)(61400799027)(376014)(32142699015)(9140799003)(48200799018)(22082099003)(10067099003)(5063699009)(56012099006)(18002099003)(16102099003)(5113699003)(4143699003)(55112099003)(4113699003)(13003099007);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: IlVeTzt9hLc9Q8inXYk/+bFWDRI9fchHq/GY8xLOaNg8ddFT+wId3U038glXafVs8oKqFgzCmZuYY6zEjbIgGpfu4RwGOpX5Df1nIxdCVO6ogut0y0pNThOzp1K8vDcEU5vApYAzZL8VNVSSP75nR3ARr+4rCoh+1iOtGe1PpXRy5CR+d14wmWSxuzKe+bKB8yOkVzXYBN9xFxRdajthSVYrKyeuLvdjn2MzZS686XQp0YkQuizDRL8VGQSd2e7dQgQlhKmXiDXhEjwwT9V+tEjwV2G9ifqHwRWIqZJJXLyBwhG/817JG8JohLoIcaAgKYL8T+jiRmLKuZ+qgo17jr+p6sSV6bKsxxL/nJD1RHW3B0CR3jhDJ8zZ4wT02wJBn705gAJEVULI8/5p/68SlDYuZYjMFQKnRGvGrtaYjtACl1bks5EIjoLfEmZRZflX X-ExternalRecipientOutboundConnectors: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-Auto-Response-Suppress: DR, OOF, AutoReply X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Oct 2026 16:50:24.3152 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f0399b97-4508-46af-9f4f-08df23c9eac4 X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF00028CFE.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR08MB8228 Thank you for your contribution! Sashiko AI review found 4 potential issue(= s) to consider: - [Medium] usb-host: cpr-transfer target takes fd ownership in post_load() = before migration commits - [Medium] usb-host: target usb_host_open() fail path resets shared device = before cpr_handed_off is set - [Low] usb-host: cpr_handed_off left set on source after failed cpr-transf= er with VM paused - [Low] usb-host: cpr_handed_off guard in usb_host_close() also skips logic= al detach and cleanup -- commit 642a3db85ee636f9e50d1ff27121f39b2c1b9026 Author: Andrey Drobyshev usb-host: hand off the device across cpr-transfer #VSTOR-137800 This patch hands reaping of the shared usbfs fd from the cpr-transfer sourc= e to the target. The target stops events in realize() and restarts them in = post_load(). The source stops events when it quiesces and restarts them on = resume. On success the source's exit path leaves the device untouched. > diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c > --- a/hw/usb/host-libusb.c > +++ b/hw/usb/host-libusb.c [ ... ] > @@ -1285,13 +1306,18 @@ static int usb_host_cpr_drain_xfers(USBHostDevice= *s) > static int usb_host_cpr_quiesce(USBHostDevice *s, MigMode mode) > { > if (usb_host_cpr_drain_xfers(s) < 0) { > return -1; > } > + if (mode =3D=3D MIG_MODE_CPR_TRANSFER) { > + usb_host_stop_events(); > + s->cpr_handed_off =3D true; > + } > return 0; > } [Severity: Low] cpr_handed_off is set here before the outcome of the handoff is known. It is cleared only on VM resume (usb_host_cpr_reissue()) or device_del (usb_host_unrealize()). The same applies to the usb_host_pre_save() fallback for an already-paused VM, which also calls usb_host_cpr_quiesce(). Suppose the cpr-transfer migration fails or is cancelled and the VM stays paused. The resume branch never runs, so the flag stays set and reaping stays stopped for the whole libusb context. A later QEMU quit then reaches usb_host_exit_notifier(): if (!s->cpr_handed_off) { usb_host_abort_xfers(s); usb_host_release_interfaces(s); libusb_reset_device(s->dh); usb_host_attach_kernel(s); } libusb_close(s->dh); Can this path tell a failed handoff from a successful one? As written, it skips the reset and the host driver rebind even though no handoff happened. [ ... ] > @@ -1310,6 +1336,11 @@ static void usb_host_cpr_reissue(USBHostDevice *s) > return; > } > =20 > + if (s->cpr_handed_off) { > + usb_host_start_events(); > + s->cpr_handed_off =3D false; > + } [Severity: Medium] Following the failed-migration path, the source resumes and restarts reaping here. If the target already called usb_host_start_events() in usb_host_post_load(), both processes now reap URBs on the shared fd. See the comment on usb_host_post_load() below. > @@ -1384,16 +1415,19 @@ static int usb_host_close(USBHostDevice *s) > =20 > trace_usb_host_close(s->bus_num, s->addr); > =20 > - usb_host_abort_xfers(s); > - usb_host_iso_free_all(s); > + if (!s->cpr_handed_off) { > + usb_host_abort_xfers(s); > + usb_host_iso_free_all(s); > =20 > - if (udev->attached) { > - usb_device_detach(udev); > + if (udev->attached) { > + usb_device_detach(udev); > + } > + > + usb_host_release_interfaces(s); > + libusb_reset_device(s->dh); > + usb_host_attach_kernel(s); > } [Severity: Low] This guard covers more than the physical reset, release and rebind. It also skips usb_host_abort_xfers(), usb_host_iso_free_all() and usb_device_detach(). Should only the physical operations be gated? Two callers can reach this with the flag set: usb_host_realize() usb_host_open() -> usb_device_attach() migrate_add_blocker_modes() fails usb_host_close() -> usb_device_detach() skipped On the target, the attach done by usb_host_open() is never paired with a detach. usb_qdev_realize() only calls usb_release_port() on failure, so the port is left with a stale attach. usb_host_nodev_bh() usb_host_close() If a surprise removal occurs between the source's quiesce and resume, the handle is closed without detaching the device from the guest. The guest then sees NODEV errors instead of a detach, while s->dh is NULL. [ ... ] > @@ -1500,6 +1541,18 @@ static void usb_host_realize(USBDevice *udev, Erro= r **errp) > error_setg(errp, "failed to open host usb device %s", s->hos= tdevice); > return; > } > + if (cpr_get_incoming_mode() =3D=3D MIG_MODE_CPR_TRANSFER) { > + [ ... ] > + usb_host_stop_events(); > + s->cpr_handed_off =3D true; > + } [Severity: Medium] The flag and the event stop are applied only after usb_host_open() has succeeded. Can the failure path inside usb_host_open() reset the device under the live source? usb_host_realize() cpr_open_fd() usb_host_open(s, NULL, fd) ... fail: usb_host_release_interfaces(s); libusb_reset_device(s->dh); usb_host_attach_kernel(s); libusb_close(s->dh); usb_host_open() does real work on the shared fd: libusb_wrap_sys_device(), usb_host_detach_kernel(), usb_host_ep_update() and usb_device_attach(). If a later step fails, for example usb_device_attach() rejecting a speed mismatch, the fail: label runs unconditionally and is not gated by cpr_handed_off. This conflicts with the commit message statement that the target "must not touch the device at all" until it takes over. [ ... ] > @@ -1563,6 +1616,17 @@ static void usb_host_unrealize(USBDevice *udev) > [ ... ] > + if (s->cpr_handed_off && !cpr_is_incoming()) { > + usb_host_start_events(); > + s->cpr_handed_off =3D false; > + } > usb_host_close(s); [Severity: Medium] migration_incoming_state_destroy() calls cpr_set_incoming_mode(MIG_MODE_NON= E), so cpr_is_incoming() becomes false once an incoming migration has failed. Consider a target that survives the failure, for example with exit-on-error off, and still has cpr_handed_off =3D=3D true. A device_del then takes the = "we own it" branch. It restarts events and runs the full reset and release while the source has resumed with the device. Is cpr_is_incoming() a reliable test for "the source still drives the fd" here? [ ... ] > @@ -2046,6 +2110,9 @@ static int usb_host_post_load(void *opaque, int ver= sion_id) > */ > if (cpr_is_incoming()) { > + usb_host_start_events(); > + /* the takeover is complete: from here on this process owns the = fd */ > + dev->cpr_handed_off =3D false; > return 0; > } [Severity: Medium] Ownership is taken here when this device's vmstate section is loaded, not when the whole migration has succeeded. Later device sections, the end of the stream and the source-side completion all come after this point. If the migration fails after this section loads, for example from a later device's load error, a broken stream or a cancel, the source resumes. Then usb_host_cpr_reissue() restarts its own reaping: target: usb_host_post_load() usb_host_start_events(); dev->cpr_handed_off =3D false; source: usb_host_cpr_vm_state() -> usb_host_cpr_reissue() usb_host_start_events(); Both processes then reap URBs on the same usbfs fd. This is the situation the commit message says must be avoided, since one process can reap the other's in-flight isochronous completions. When the target then exits, usb_host_exit_notifier() sees cpr_handed_off =3D=3D false and runs: usb_host_abort_xfers(s); usb_host_release_interfaces(s); libusb_reset_device(s->dh); usb_host_attach_kernel(s); This resets the device and rebinds the host driver under the resumed source, which the commit message says the target's exit must not do. Could the takeover be deferred until the migration has committed, so a late failure leaves the target's flag set and its events stopped? --=20 Sashiko AI review =C2=B7 https://sashiko.vzint.dev/#/patchset/20261006-usb-= host_v3-v8-0-72ae4fb8977b@virtuozzo.com?part=3D10