aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi/virtio-scsi.c
diff options
context:
space:
mode:
authorMaxim Levitsky <mlevitsk@redhat.com>2020-10-06 15:38:59 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2020-10-12 11:50:50 -0400
commit2d24a64661549732fc77f632928318dd52f5bce5 (patch)
tree3e7f20a87ef9c2368db3f988fe331279cacf236a /hw/scsi/virtio-scsi.c
parent7bed89958bfbf40df9ca681cefbdca63abdde39d (diff)
downloadqemu-2d24a64661549732fc77f632928318dd52f5bce5.zip
qemu-2d24a64661549732fc77f632928318dd52f5bce5.tar.gz
qemu-2d24a64661549732fc77f632928318dd52f5bce5.tar.bz2
device-core: use RCU for list of children of a bus
This fixes the race between device emulation code that tries to find a child device to dispatch the request to (e.g a scsi disk), and hotplug of a new device to that bus. Note that this doesn't convert all the readers of the list but only these that might go over that list without BQL held. This is a very small first step to make this code thread safe. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-Id: <20200913160259.32145-5-mlevitsk@redhat.com> [Use RCU_READ_LOCK_GUARD in more places, adjust testcase now that the delay in DEVICE_DELETED due to RCU is more consistent. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20201006123904.610658-9-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/scsi/virtio-scsi.c')
-rw-r--r--hw/scsi/virtio-scsi.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 3a71ea7..971afbb 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -367,12 +367,16 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
target = req->req.tmf.lun[1];
s->resetting++;
- QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+
+ rcu_read_lock();
+ QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
d = SCSI_DEVICE(kid->child);
if (d->channel == 0 && d->id == target) {
qdev_reset_all(&d->qdev);
}
}
+ rcu_read_unlock();
+
s->resetting--;
break;