aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi/scsi-bus.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2023-05-16 15:02:21 -0400
committerKevin Wolf <kwolf@redhat.com>2023-05-30 17:32:02 +0200
commit4382f167cfbc21a49424e6dd9347681008363128 (patch)
treeaa0b779babed08f5f208e029191c70f494e0177d /hw/scsi/scsi-bus.c
parent26462a700c8c5d30802c2254a35b5064762e00f0 (diff)
downloadqemu-4382f167cfbc21a49424e6dd9347681008363128.zip
qemu-4382f167cfbc21a49424e6dd9347681008363128.tar.gz
qemu-4382f167cfbc21a49424e6dd9347681008363128.tar.bz2
virtio-scsi: avoid race between unplug and transport event
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. Change virtio_scsi_push_event() to take event information as an argument instead of the SCSIDevice. This allows virtio_scsi_hotunplug() to emit a VIRTIO_SCSI_T_TRANSPORT_RESET event after the SCSIDevice has already been 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. Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-Id: <20230516190238.8401-4-stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw/scsi/scsi-bus.c')
-rw-r--r--hw/scsi/scsi-bus.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 8857ff4..64013c8 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 &&
+ qdev_is_realized(&dev->qdev)) {
store_lun(tmp, dev->lun);
g_byte_array_append(buf, tmp, 8);
len += 8;