aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2023-02-21 16:22:18 -0500
committerKevin Wolf <kwolf@redhat.com>2023-02-23 19:49:35 +0100
commitbe2c42b97c3a3a395b2f05bad1b6c7de20ecf2a5 (patch)
treebce5724a3175d54f879be2adb24a716a61bfd86c /include
parentabfcd2760b3e70727bbc0792221b8b98a733dc32 (diff)
virtio-scsi: reset SCSI devices from main loop thread
When an IOThread is configured, the ctrl virtqueue is processed in the IOThread. TMFs that reset SCSI devices are currently called directly from the IOThread and trigger an assertion failure in blk_drain() from the following call stack: virtio_scsi_handle_ctrl_req -> virtio_scsi_do_tmf -> device_code_reset -> scsi_disk_reset -> scsi_device_purge_requests -> blk_drain ../block/block-backend.c:1780: void blk_drain(BlockBackend *): Assertion `qemu_in_main_thread()' failed. The blk_drain() function is not designed to be called from an IOThread because it needs the Big QEMU Lock (BQL). This patch defers TMFs that reset SCSI devices to a Bottom Half (BH) that runs in the main loop thread under the BQL. This way it's safe to call blk_drain() and the assertion failure is avoided. Introduce s->tmf_bh_list for tracking TMF requests that have been deferred to the BH. When the BH runs it will grab the entire list and process all requests. Care must be taken to clear the list when the virtio-scsi device is reset or unrealized. Otherwise deferred TMF requests could execute later and lead to use-after-free or other undefined behavior. The s->resetting counter that's used by TMFs that reset SCSI devices is accessed from multiple threads. This patch makes that explicit by using atomic accessor functions. With this patch applied the counter is only modified by the main loop thread under the BQL but can be read by any thread. Reported-by: Qing Wang <qinwang@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Message-Id: <20230221212218.1378734-4-stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/hw/virtio/virtio-scsi.h11
1 files changed, 10 insertions, 1 deletions
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 37b75e15e3..779568ab5d 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -74,13 +74,22 @@ struct VirtIOSCSICommon {
VirtQueue **cmd_vqs;
};
+struct VirtIOSCSIReq;
+
struct VirtIOSCSI {
VirtIOSCSICommon parent_obj;
SCSIBus bus;
- int resetting;
+ int resetting; /* written from main loop thread, read from any thread */
bool events_dropped;
+ /*
+ * TMFs deferred to main loop BH. These fields are protected by
+ * virtio_scsi_acquire().
+ */
+ QEMUBH *tmf_bh;
+ QTAILQ_HEAD(, VirtIOSCSIReq) tmf_bh_list;
+
/* Fields for dataplane below */
AioContext *ctx; /* one iothread per virtio-scsi-pci for now */