Virtuozzo QEMU development (svt-core@virtuozzo.com)
 help / color / mirror / Atom feed
* [PATCH hci-8.1 0/1] virtio-scsi: fix hot-plugged disk invisible in the guest #VSTOR-151351
@ 2026-10-26 11:11 Denis V. Lunev
  2026-10-26 11:11 ` [PATCH hci-8.1 1/1] virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351 Denis V. Lunev
  0 siblings, 1 reply; 4+ messages in thread
From: Denis V. Lunev @ 2026-10-26 11:11 UTC (permalink / raw)
  To: andrey.drobyshev; +Cc: svt-core, den

A disk or CD-ROM hot-plugged into virtio-scsi sometimes never shows up
in the guest until the bus is rescanned by hand. CI hits it with Windows
Server guests (vioscsi) and with Linux guests, always with the controller
on an iothread: VSTOR-151351, VSTOR-147722, VSTOR-150741 and the Linux
tickets VSTOR-146483, 146499, 146614 and 147072.

The RESCAN event is pushed from the plug() callback, before the device
is realized, and the iothread request path does not see unrealized
devices. A guest that scans right away gets BAD_TARGET and does not
retry. The patch moves the event to a main-loop bottom half. Ilya Rudakov
found the cause.

This is the patch posted to qemu-devel on 2026-10-23, not yet merged:
https://lore.kernel.org/qemu-devel/20261023162000.2796947-1-den@openvz.org/
The only difference is the non-const HotplugHandler argument of
virtio_scsi_hotplug() in our tree.

There is no test in the patch: a qtest or iotests client is served by
the main loop and cannot get a request into the window inside
device_add. On the upstream build, a Linux guest with the main thread
stalled for 3 s in scsi_bus_set_ua() under gdb missed the hot-plugged
LUN in 3 of 3 runs without the fix and saw it in 3 of 3 with it. On this
tree, hw/scsi/virtio-scsi.c only has been build-checked.

Signed-off-by: Denis V. Lunev <den@openvz.org>

Denis V. Lunev (1):
  virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351

 hw/scsi/virtio-scsi.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)


base-commit: f3c1d9ef263edfab8d2a273078493bb766dcf8f8
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH hci-8.1 1/1] virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351
  2026-10-26 11:11 [PATCH hci-8.1 0/1] virtio-scsi: fix hot-plugged disk invisible in the guest #VSTOR-151351 Denis V. Lunev
@ 2026-10-26 11:11 ` Denis V. Lunev
  2026-10-26 11:14   ` no-reply
  2026-10-26 11:29   ` Andrey Drobyshev
  0 siblings, 2 replies; 4+ messages in thread
From: Denis V. Lunev @ 2026-10-26 11:11 UTC (permalink / raw)
  To: andrey.drobyshev; +Cc: svt-core, den

From: Denis V. Lunev <den@openvz.org>

virtio_scsi_hotplug() is the HotplugHandler plug() callback, which
device_set_realized() calls before it sets dev->realized. The callback
pushes VIRTIO_SCSI_T_TRANSPORT_RESET/RESCAN to the guest at once, but
until realized is set the request path ignores the new device:
virtio_scsi_device_get() -> scsi_device_get() skips unrealized devices,
and so does REPORT LUNS. A guest that reacts to the event quickly, on a
vCPU while the request queue is served by an iothread, scans the target
and gets VIRTIO_SCSI_S_BAD_TARGET.

Neither Linux nor Windows retries that scan, so the hot-plugged disk or
CD-ROM stays invisible until somebody rescans the bus by hand. Linux
calls scsi_scan_target() once from the event handler. Windows storport
clears its rescan flag before enumerating the bus and never sets it
again for a failed target.

Push the event, and the REPORTED LUNS CHANGED unit attention that goes
with it, from a main-loop bottom half instead. It runs under the BQL,
which device_add holds until device_set_realized() returns, so the guest
is only told about a device it can reach. The iothread context would not
do: its bottom half could run before realized is set, and the realized
check and scsi_bus_set_ua() rely on the BQL as plug() did. The bottom
half is only scheduled when the guest negotiated VIRTIO_SCSI_F_HOTPLUG,
as before, so cold-plugged devices do not get one. It still checks that
the device is realized: nothing orders it against a device_del that
follows device_add, and an unplugged device has no parent bus.

Fixes: 8ddf958e8d62 ("scsi/scsi-bus: scsi_device_find: don't return unrealized devices")
Cc: qemu-stable@nongnu.org
Reported-by: Ilya Rudakov <irudakov@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Fam Zheng <fam@euphon.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
---
 hw/scsi/virtio-scsi.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 3b635053b56..69b34adde22 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -1145,6 +1145,29 @@ static void virtio_scsi_pre_hotplug(HotplugHandler *hotplug_dev,
     sd->hba_supports_iothread = true;
 }
 
+static void virtio_scsi_hotplug_notify_bh(void *opaque)
+{
+    SCSIDevice *sd = opaque;
+    DeviceState *dev = DEVICE(sd);
+
+    /* Nothing orders us against a following device_del */
+    if (qdev_is_realized(dev)) {
+        VirtIOSCSI *s = VIRTIO_SCSI(dev->parent_bus->parent);
+        VirtIOSCSIEventInfo info = {
+            .event   = VIRTIO_SCSI_T_TRANSPORT_RESET,
+            .reason  = VIRTIO_SCSI_EVT_RESET_RESCAN,
+            .address = {
+                .id  = sd->id,
+                .lun = sd->lun,
+            },
+        };
+
+        virtio_scsi_push_event(s, &info);
+        scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED));
+    }
+    object_unref(OBJECT(sd));
+}
+
 static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                 Error **errp)
 {
@@ -1163,17 +1186,10 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
     }
 
     if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
-        VirtIOSCSIEventInfo info = {
-            .event   = VIRTIO_SCSI_T_TRANSPORT_RESET,
-            .reason  = VIRTIO_SCSI_EVT_RESET_RESCAN,
-            .address = {
-                .id  = sd->id,
-                .lun = sd->lun,
-            },
-        };
-
-        virtio_scsi_push_event(s, &info);
-        scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED));
+        /* The request path ignores @sd until it is realized, so notify after */
+        object_ref(OBJECT(sd));
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                virtio_scsi_hotplug_notify_bh, sd);
     }
 }
 
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH hci-8.1 1/1] virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351
  2026-10-26 11:11 ` [PATCH hci-8.1 1/1] virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351 Denis V. Lunev
@ 2026-10-26 11:14   ` no-reply
  2026-10-26 11:29   ` Andrey Drobyshev
  1 sibling, 0 replies; 4+ messages in thread
From: no-reply @ 2026-10-26 11:14 UTC (permalink / raw)
  To: Denis V. Lunev, andrey.drobyshev; +Cc: den, svt-core

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] virtio-scsi: commit subject carries downstream tracker tag #VSTOR-151351
--

commit 6ce8922336ce923544c647be9bf402727f9af695
Author: Denis V. Lunev <den@openvz.org>

virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351

This commit moves the TRANSPORT_RESET/RESCAN event and the REPORTED LUNS
CHANGED unit attention out of virtio_scsi_hotplug() and into a main-loop
bottom half. The bottom half runs after the device is realized, so the
guest can reach the device when it scans. The bottom half takes a
reference on the SCSIDevice and re-checks that the device is still
realized before pushing the event.

> virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351

[Severity: Low]
This isn't a bug, but the subject line carries a downstream tracker tag,
"#VSTOR-151351". It is a Virtuozzo bug-tracker ID and doesn't follow the
usual "subsystem: summary" subject form. The patch is Cc'd to
qemu-stable, so the tag would also be carried into stable trees.

Could the tag be dropped from the subject, or moved into the body or a
trailer?

> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c

[ ... ]

> @@ -1163,17 +1186,10 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
>      }
>  
>      if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
> -        VirtIOSCSIEventInfo info = {
[ ... ]
> +        /* The request path ignores @sd until it is realized, so notify after */
> +        object_ref(OBJECT(sd));
> +        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> +                                virtio_scsi_hotplug_notify_bh, sd);
>      }
>  }

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261026111113.145378-1-den@openvz.org?part=1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH hci-8.1 1/1] virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351
  2026-10-26 11:11 ` [PATCH hci-8.1 1/1] virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351 Denis V. Lunev
  2026-10-26 11:14   ` no-reply
@ 2026-10-26 11:29   ` Andrey Drobyshev
  1 sibling, 0 replies; 4+ messages in thread
From: Andrey Drobyshev @ 2026-10-26 11:29 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: svt-core

LGTM
Ack, applied to hci-dev

On 10/26/26 1:11 PM, Denis V. Lunev wrote:
> From: Denis V. Lunev <den@openvz.org>
> 
> virtio_scsi_hotplug() is the HotplugHandler plug() callback, which
> device_set_realized() calls before it sets dev->realized. The callback
> pushes VIRTIO_SCSI_T_TRANSPORT_RESET/RESCAN to the guest at once, but
> until realized is set the request path ignores the new device:
> virtio_scsi_device_get() -> scsi_device_get() skips unrealized devices,
> and so does REPORT LUNS. A guest that reacts to the event quickly, on a
> vCPU while the request queue is served by an iothread, scans the target
> and gets VIRTIO_SCSI_S_BAD_TARGET.
> 
> Neither Linux nor Windows retries that scan, so the hot-plugged disk or
> CD-ROM stays invisible until somebody rescans the bus by hand. Linux
> calls scsi_scan_target() once from the event handler. Windows storport
> clears its rescan flag before enumerating the bus and never sets it
> again for a failed target.
> 
> Push the event, and the REPORTED LUNS CHANGED unit attention that goes
> with it, from a main-loop bottom half instead. It runs under the BQL,
> which device_add holds until device_set_realized() returns, so the guest
> is only told about a device it can reach. The iothread context would not
> do: its bottom half could run before realized is set, and the realized
> check and scsi_bus_set_ua() rely on the BQL as plug() did. The bottom
> half is only scheduled when the guest negotiated VIRTIO_SCSI_F_HOTPLUG,
> as before, so cold-plugged devices do not get one. It still checks that
> the device is realized: nothing orders it against a device_del that
> follows device_add, and an unplugged device has no parent bus.
> 
> Fixes: 8ddf958e8d62 ("scsi/scsi-bus: scsi_device_find: don't return unrealized devices")
> Cc: qemu-stable@nongnu.org
> Reported-by: Ilya Rudakov <irudakov@virtuozzo.com>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Fam Zheng <fam@euphon.net>
> Cc: "Michael S. Tsirkin" <mst@redhat.com>
> ---
>  hw/scsi/virtio-scsi.c | 38 +++++++++++++++++++++++++++-----------
>  1 file changed, 27 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> index 3b635053b56..69b34adde22 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -1145,6 +1145,29 @@ static void virtio_scsi_pre_hotplug(HotplugHandler *hotplug_dev,
>      sd->hba_supports_iothread = true;
>  }
>  
> +static void virtio_scsi_hotplug_notify_bh(void *opaque)
> +{
> +    SCSIDevice *sd = opaque;
> +    DeviceState *dev = DEVICE(sd);
> +
> +    /* Nothing orders us against a following device_del */
> +    if (qdev_is_realized(dev)) {
> +        VirtIOSCSI *s = VIRTIO_SCSI(dev->parent_bus->parent);
> +        VirtIOSCSIEventInfo info = {
> +            .event   = VIRTIO_SCSI_T_TRANSPORT_RESET,
> +            .reason  = VIRTIO_SCSI_EVT_RESET_RESCAN,
> +            .address = {
> +                .id  = sd->id,
> +                .lun = sd->lun,
> +            },
> +        };
> +
> +        virtio_scsi_push_event(s, &info);
> +        scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED));
> +    }
> +    object_unref(OBJECT(sd));
> +}
> +
>  static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
>                                  Error **errp)
>  {
> @@ -1163,17 +1186,10 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
>      }
>  
>      if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
> -        VirtIOSCSIEventInfo info = {
> -            .event   = VIRTIO_SCSI_T_TRANSPORT_RESET,
> -            .reason  = VIRTIO_SCSI_EVT_RESET_RESCAN,
> -            .address = {
> -                .id  = sd->id,
> -                .lun = sd->lun,
> -            },
> -        };
> -
> -        virtio_scsi_push_event(s, &info);
> -        scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED));
> +        /* The request path ignores @sd until it is realized, so notify after */
> +        object_ref(OBJECT(sd));
> +        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> +                                virtio_scsi_hotplug_notify_bh, sd);
>      }
>  }
>  


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-26 11:29 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26 11:11 [PATCH hci-8.1 0/1] virtio-scsi: fix hot-plugged disk invisible in the guest #VSTOR-151351 Denis V. Lunev
2026-10-26 11:11 ` [PATCH hci-8.1 1/1] virtio-scsi: fix hot-plug event racing device realize #VSTOR-151351 Denis V. Lunev
2026-10-26 11:14   ` no-reply
2026-10-26 11:29   ` Andrey Drobyshev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox