aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2014-05-08 16:34:36 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2014-06-04 09:56:11 +0200
commit9b536adcbefb72090f43c9715ce042e37e47af73 (patch)
treec6b444f41da20810ea093f62f1daafb84931a7dc /block.c
parented78cda3de92056737364ab3cb748b16f5f17dea (diff)
block: acquire AioContext in bdrv_drain_all()
Modify bdrv_drain_all() to take into account that BlockDriverState instances may be running in different AioContexts. This patch changes the implementation of bdrv_drain_all() while preserving the semantics. Previously kicking throttled requests and checking for pending requests were done across all BlockDriverState instances in sequence. Now we process each BlockDriverState in turn, making sure to acquire and release its AioContext. This prevents race conditions between the thread executing bdrv_drain_all() and the thread running the AioContext. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block.c')
-rw-r--r--block.c25
1 files changed, 11 insertions, 14 deletions
diff --git a/block.c b/block.c
index 7cccb84dab..87da79fbe8 100644
--- a/block.c
+++ b/block.c
@@ -1885,17 +1885,6 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
return false;
}
-static bool bdrv_requests_pending_all(void)
-{
- BlockDriverState *bs;
- QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
- if (bdrv_requests_pending(bs)) {
- return true;
- }
- }
- return false;
-}
-
/*
* Wait for pending requests to complete across all BlockDriverStates
*
@@ -1915,12 +1904,20 @@ void bdrv_drain_all(void)
BlockDriverState *bs;
while (busy) {
+ busy = false;
+
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+ bool bs_busy;
+
+ aio_context_acquire(aio_context);
bdrv_start_throttled_reqs(bs);
- }
+ bs_busy = bdrv_requests_pending(bs);
+ bs_busy |= aio_poll(aio_context, bs_busy);
+ aio_context_release(aio_context);
- busy = bdrv_requests_pending_all();
- busy |= aio_poll(qemu_get_aio_context(), busy);
+ busy |= bs_busy;
+ }
}
}