summaryrefslogtreecommitdiff
path: root/block/stream.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2013-04-11 15:41:13 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2013-08-19 15:45:34 +0200
commit88266f5aa70fa71fd5cc20aa4dbeb7a7bd8d2e92 (patch)
tree59a8cc958f76256abfa69357edc131b69c566d8d /block/stream.c
parente1b5c52e04d04bb93546c6e37e8884889d047cb1 (diff)
downloadqemu-88266f5aa70fa71fd5cc20aa4dbeb7a7bd8d2e92.tar.gz
block: stop relying on io_flush() in bdrv_drain_all()
If a block driver has no file descriptors to monitor but there are still active requests, it can return 1 from .io_flush(). This is used to spin during synchronous I/O. Stop relying on .io_flush() and instead check QLIST_EMPTY(&bs->tracked_requests) to decide whether there are active requests. This is the first step in removing .io_flush() so that event loops no longer need to have the concept of synchronous I/O. Eventually we may be able to kill synchronous I/O completely by running everything in a coroutine, but that is future work. Note this patch moves bs->throttled_reqs initialization to bdrv_new() so that bdrv_requests_pending(bs) can safely access it. In practice bs is g_malloc0() so the memory is already zeroed but it's safer to initialize the queue properly. We also need to fix up block/stream.c:close_unused_images() to prevent traversing a dangling pointer while it rearranges the backing file chain. This is necessary since the new bdrv_drain_all() traverses the backing file chain. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/stream.c')
-rw-r--r--block/stream.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/block/stream.c b/block/stream.c
index 7fe9e486bf..db49b4d85f 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -57,6 +57,11 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
BlockDriverState *intermediate;
intermediate = top->backing_hd;
+ /* Must assign before bdrv_delete() to prevent traversing dangling pointer
+ * while we delete backing image instances.
+ */
+ top->backing_hd = base;
+
while (intermediate) {
BlockDriverState *unused;
@@ -70,7 +75,6 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
unused->backing_hd = NULL;
bdrv_delete(unused);
}
- top->backing_hd = base;
}
static void coroutine_fn stream_run(void *opaque)