summaryrefslogtreecommitdiff
path: root/hw/block
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2013-09-04 14:16:15 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2013-09-06 15:25:09 +0200
commit8caf907f07688972e5e7cd11526079b1665d6dba (patch)
tree0b8f280f58f6cbc5d96865eee443a38dbcbb17b9 /hw/block
parent5daa74a6ebce7543aaad178c4061dc087bb4c705 (diff)
downloadqemu-8caf907f07688972e5e7cd11526079b1665d6dba.tar.gz
dataplane: Fix startup race.
Avoid trying to setup dataplane again if dataplane setup is already in progress. This may happen if an eventfd is triggered during setup. I saw this occasionally with an experimental s390 irqfd implementation: virtio_blk_handle_output -> virtio_blk_data_plane_start -> virtio_ccw_set_host_notifier ... -> virtio_queue_set_host_notifier_fd_handler -> virtio_queue_host_notifier_read -> virtio_queue_notify_vq -> virtio_blk_handle_output -> virtio_blk_data_plane_start -> vring_setup -> hostmem_init -> memory_listener_register -> BOOM As virtio-ccw tries to follow what virtio-pci does, it might be triggerable for other platforms as well. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/block')
-rw-r--r--hw/block/dataplane/virtio-blk.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 5a96ccd416..f2d7350a50 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -42,6 +42,7 @@ typedef struct {
struct VirtIOBlockDataPlane {
bool started;
+ bool starting;
bool stopping;
QEMUBH *start_bh;
QemuThread thread;
@@ -451,8 +452,15 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
return;
}
+ if (s->starting) {
+ return;
+ }
+
+ s->starting = true;
+
vq = virtio_get_queue(s->vdev, 0);
if (!vring_setup(&s->vring, s->vdev, 0)) {
+ s->starting = false;
return;
}
@@ -482,6 +490,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
s->io_notifier = *ioq_get_notifier(&s->ioqueue);
aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io);
+ s->starting = false;
s->started = true;
trace_virtio_blk_data_plane_start(s);