qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] virtio-scsi: stop using aio_disable_external() during unplug
@ 2023-03-23 18:56 Stefan Hajnoczi
  2023-03-23 18:56 ` [PATCH 1/2] virtio-scsi: avoid race between unplug and transport event Stefan Hajnoczi
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Stefan Hajnoczi @ 2023-03-23 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Michael S. Tsirkin, Fam Zheng, kwolf, qemu-block,
	Stefan Hajnoczi

The aio_disable_external() API is a solution for stopping I/O during critical
sections. The newer BlockDevOps->drained_begin/end/poll() callbacks offer a
cleaner solution that supports the upcoming multi-queue block layer. This
series removes aio_disable_external() from the virtio-scsi emulation code.

Patch 1 is a fix for something I noticed when reading the code.

Patch 2 replaces aio_disable_external() with functionality for safe hot unplug
that's mostly already present in the SCSI emulation code.

Stefan Hajnoczi (2):
  virtio-scsi: avoid race between unplug and transport event
  virtio-scsi: stop using aio_disable_external() during unplug

 hw/scsi/scsi-bus.c    |  3 ++-
 hw/scsi/scsi-disk.c   |  1 +
 hw/scsi/virtio-scsi.c | 21 +++++++++------------
 3 files changed, 12 insertions(+), 13 deletions(-)

-- 
2.39.2



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

* [PATCH 1/2] virtio-scsi: avoid race between unplug and transport event
  2023-03-23 18:56 [PATCH 0/2] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
@ 2023-03-23 18:56 ` Stefan Hajnoczi
  2023-03-23 18:56 ` [PATCH 2/2] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
  2023-04-04 10:21 ` [PATCH 0/2] " Daniil Tatianin
  2 siblings, 0 replies; 4+ messages in thread
From: Stefan Hajnoczi @ 2023-03-23 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Michael S. Tsirkin, Fam Zheng, kwolf, qemu-block,
	Stefan Hajnoczi

Only report a transport reset event to the guest after the SCSIDevice
has been unrealized by qdev_simple_device_unplug_cb().

qdev_simple_device_unplug_cb() sets the SCSIDevice's qdev.realized field
to false so that scsi_device_find/get() no longer see it.

scsi_target_emulate_report_luns() also needs to be updated to filter out
SCSIDevices that are unrealized.

These changes ensure that the guest driver does not see the SCSIDevice
that's being unplugged if it responds very quickly to the transport
reset event.

I noticed this issue when reading the code and have not reproduced it.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/scsi/scsi-bus.c    |  3 ++-
 hw/scsi/virtio-scsi.c | 18 +++++++++---------
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index c97176110c..f9bd064833 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -487,7 +487,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
             DeviceState *qdev = kid->child;
             SCSIDevice *dev = SCSI_DEVICE(qdev);
 
-            if (dev->channel == channel && dev->id == id && dev->lun != 0) {
+            if (dev->channel == channel && dev->id == id && dev->lun != 0 &&
+                qatomic_load_acquire(&dev->qdev.realized)) {
                 store_lun(tmp, dev->lun);
                 g_byte_array_append(buf, tmp, 8);
                 len += 8;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 612c525d9d..000961446c 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -1063,15 +1063,6 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
     SCSIDevice *sd = SCSI_DEVICE(dev);
     AioContext *ctx = s->ctx ?: qemu_get_aio_context();
 
-    if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
-        virtio_scsi_acquire(s);
-        virtio_scsi_push_event(s, sd,
-                               VIRTIO_SCSI_T_TRANSPORT_RESET,
-                               VIRTIO_SCSI_EVT_RESET_REMOVED);
-        scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED));
-        virtio_scsi_release(s);
-    }
-
     aio_disable_external(ctx);
     qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
     aio_enable_external(ctx);
@@ -1082,6 +1073,15 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
         blk_set_aio_context(sd->conf.blk, qemu_get_aio_context(), NULL);
         virtio_scsi_release(s);
     }
+
+    if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
+        virtio_scsi_acquire(s);
+        virtio_scsi_push_event(s, sd,
+                               VIRTIO_SCSI_T_TRANSPORT_RESET,
+                               VIRTIO_SCSI_EVT_RESET_REMOVED);
+        scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED));
+        virtio_scsi_release(s);
+    }
 }
 
 static struct SCSIBusInfo virtio_scsi_scsi_info = {
-- 
2.39.2



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

* [PATCH 2/2] virtio-scsi: stop using aio_disable_external() during unplug
  2023-03-23 18:56 [PATCH 0/2] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
  2023-03-23 18:56 ` [PATCH 1/2] virtio-scsi: avoid race between unplug and transport event Stefan Hajnoczi
@ 2023-03-23 18:56 ` Stefan Hajnoczi
  2023-04-04 10:21 ` [PATCH 0/2] " Daniil Tatianin
  2 siblings, 0 replies; 4+ messages in thread
From: Stefan Hajnoczi @ 2023-03-23 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Michael S. Tsirkin, Fam Zheng, kwolf, qemu-block,
	Stefan Hajnoczi, Zhengui Li

This patch is part of an effort to remove the aio_disable_external()
API because it does not fit in a multi-queue block layer world where
many AioContexts may be submitting requests to the same disk.

The SCSI emulation code is already in good shape to stop using
aio_disable_external(). The API is only used by commit 9c5aad84da1c
("virtio-scsi: fixed virtio_scsi_ctx_check failed when detaching scsi
disk") to ensure that virtio_scsi_hotunplug() works while the guest
driver is submitting I/O.

Ensure virtio_scsi_hotunplug() is safe as follows:

1. qdev_simple_device_unplug_cb() -> qdev_unrealize() ->
   device_set_realized() calls qatomic_set(&dev->realized, false) so
   that future scsi_device_get() calls return NULL because they exclude
   SCSIDevices with realized=false.

   That means virtio-scsi will reject new I/O requests to this
   SCSIDevice with VIRTIO_SCSI_S_BAD_TARGET even while
   virtio_scsi_hotunplug() is still executing. We are protected against
   new requests!

2. Add a call to scsi_device_purge_requests() from scsi_unrealize() so
   that in-flight requests are cancelled synchronously. This ensures
   that no in-flight requests remain once qdev_simple_device_unplug_cb()
   returns.

Thanks to these two conditions we don't need aio_disable_external()
anymore.

Cc: Zhengui Li <lizhengui@huawei.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/scsi/scsi-disk.c   | 1 +
 hw/scsi/virtio-scsi.c | 3 ---
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 97c9b1c8cd..e01bd84541 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2522,6 +2522,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
 
 static void scsi_unrealize(SCSIDevice *dev)
 {
+    scsi_device_purge_requests(dev, SENSE_CODE(RESET));
     del_boot_device_lchs(&dev->qdev, NULL);
 }
 
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 000961446c..a02f9233ec 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -1061,11 +1061,8 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
     VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
     VirtIOSCSI *s = VIRTIO_SCSI(vdev);
     SCSIDevice *sd = SCSI_DEVICE(dev);
-    AioContext *ctx = s->ctx ?: qemu_get_aio_context();
 
-    aio_disable_external(ctx);
     qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
-    aio_enable_external(ctx);
 
     if (s->ctx) {
         virtio_scsi_acquire(s);
-- 
2.39.2



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

* Re: [PATCH 0/2] virtio-scsi: stop using aio_disable_external() during unplug
  2023-03-23 18:56 [PATCH 0/2] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
  2023-03-23 18:56 ` [PATCH 1/2] virtio-scsi: avoid race between unplug and transport event Stefan Hajnoczi
  2023-03-23 18:56 ` [PATCH 2/2] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
@ 2023-04-04 10:21 ` Daniil Tatianin
  2 siblings, 0 replies; 4+ messages in thread
From: Daniil Tatianin @ 2023-04-04 10:21 UTC (permalink / raw)
  To: Stefan Hajnoczi, qemu-devel
  Cc: Paolo Bonzini, Michael S. Tsirkin, Fam Zheng, kwolf, qemu-block

On 3/23/23 9:56 PM, Stefan Hajnoczi wrote:
> The aio_disable_external() API is a solution for stopping I/O during critical
> sections. The newer BlockDevOps->drained_begin/end/poll() callbacks offer a
> cleaner solution that supports the upcoming multi-queue block layer. This
> series removes aio_disable_external() from the virtio-scsi emulation code.
> 
> Patch 1 is a fix for something I noticed when reading the code.
> 
> Patch 2 replaces aio_disable_external() with functionality for safe hot unplug
> that's mostly already present in the SCSI emulation code.
> 
> Stefan Hajnoczi (2):
>    virtio-scsi: avoid race between unplug and transport event
>    virtio-scsi: stop using aio_disable_external() during unplug
> 
>   hw/scsi/scsi-bus.c    |  3 ++-
>   hw/scsi/scsi-disk.c   |  1 +
>   hw/scsi/virtio-scsi.c | 21 +++++++++------------
>   3 files changed, 12 insertions(+), 13 deletions(-)
> 

For both patches:
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>


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

end of thread, other threads:[~2023-04-04 10:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-03-23 18:56 [PATCH 0/2] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
2023-03-23 18:56 ` [PATCH 1/2] virtio-scsi: avoid race between unplug and transport event Stefan Hajnoczi
2023-03-23 18:56 ` [PATCH 2/2] virtio-scsi: stop using aio_disable_external() during unplug Stefan Hajnoczi
2023-04-04 10:21 ` [PATCH 0/2] " Daniil Tatianin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).