From 8caf907f07688972e5e7cd11526079b1665d6dba Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 4 Sep 2013 14:16:15 +0200 Subject: [PATCH] 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 Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 9 +++++++++ 1 file changed, 9 insertions(+) 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);