block: acquire AioContext in bdrv_*_all()
bdrv_close_all(), bdrv_commit_all(), bdrv_flush_all(),
bdrv_invalidate_cache_all(), and bdrv_clear_incoming_migration_all() are
called by main loop code and touch all BlockDriverState instances.
Some BlockDriverState instances may be running in another AioContext.
Make sure to acquire the AioContext before closing the BlockDriverState.
This will protect against race conditions once virtio-blk data-plane is
using the BlockDriverState from another AioContext event loop.
Note that this patch does not convert bdrv_drain_all() yet since that
conversion is non-trivial.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/block.c b/block.c
index 05ec8e1..7cccb84 100644
--- a/block.c
+++ b/block.c
@@ -1856,7 +1856,11 @@
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+
+ aio_context_acquire(aio_context);
bdrv_close(bs);
+ aio_context_release(aio_context);
}
}
@@ -2352,12 +2356,17 @@
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+
+ aio_context_acquire(aio_context);
if (bs->drv && bs->backing_hd) {
int ret = bdrv_commit(bs);
if (ret < 0) {
+ aio_context_release(aio_context);
return ret;
}
}
+ aio_context_release(aio_context);
}
return 0;
}
@@ -3833,10 +3842,15 @@
int result = 0;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
- int ret = bdrv_flush(bs);
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+ int ret;
+
+ aio_context_acquire(aio_context);
+ ret = bdrv_flush(bs);
if (ret < 0 && !result) {
result = ret;
}
+ aio_context_release(aio_context);
}
return result;
@@ -4982,7 +4996,11 @@
Error *local_err = NULL;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+
+ aio_context_acquire(aio_context);
bdrv_invalidate_cache(bs, &local_err);
+ aio_context_release(aio_context);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -4995,7 +5013,11 @@
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+
+ aio_context_acquire(aio_context);
bs->open_flags = bs->open_flags & ~(BDRV_O_INCOMING);
+ aio_context_release(aio_context);
}
}