aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/block-backend.c7
-rw-r--r--include/block/block-common.h3
-rw-r--r--scripts/block-coroutine-wrapper.py25
3 files changed, 24 insertions, 11 deletions
diff --git a/block/block-backend.c b/block/block-backend.c
index ca537cd0ad..26447664ab 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2394,9 +2394,14 @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason)
AioContext *blk_get_aio_context(BlockBackend *blk)
{
- BlockDriverState *bs = blk_bs(blk);
+ BlockDriverState *bs;
IO_CODE();
+ if (!blk) {
+ return qemu_get_aio_context();
+ }
+
+ bs = blk_bs(blk);
if (bs) {
AioContext *ctx = bdrv_get_aio_context(blk_bs(blk));
assert(ctx == blk->ctx);
diff --git a/include/block/block-common.h b/include/block/block-common.h
index 93196229ac..e15395f2cb 100644
--- a/include/block/block-common.h
+++ b/include/block/block-common.h
@@ -65,6 +65,9 @@
* scheduling a BH in the bottom half that runs the respective non-coroutine
* function. The coroutine yields after scheduling the BH and is reentered when
* the wrapped function returns.
+ *
+ * If the first parameter of the function is a BlockDriverState, BdrvChild or
+ * BlockBackend pointer, the AioContext lock for it is taken in the wrapper.
*/
#define no_co_wrapper
diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
index 60e9b3107c..d4a183db61 100644
--- a/scripts/block-coroutine-wrapper.py
+++ b/scripts/block-coroutine-wrapper.py
@@ -88,16 +88,7 @@ class FuncDecl:
raise ValueError(f"no_co function can't be rdlock: {self.name}")
self.target_name = f'{subsystem}_{subname}'
- t = self.args[0].type
- if t == 'BlockDriverState *':
- ctx = 'bdrv_get_aio_context(bs)'
- elif t == 'BdrvChild *':
- ctx = 'bdrv_get_aio_context(child->bs)'
- elif t == 'BlockBackend *':
- ctx = 'blk_get_aio_context(blk)'
- else:
- ctx = 'qemu_get_aio_context()'
- self.ctx = ctx
+ self.ctx = self.gen_ctx()
self.get_result = 's->ret = '
self.ret = 'return s.ret;'
@@ -109,6 +100,17 @@ class FuncDecl:
self.co_ret = ''
self.return_field = ''
+ def gen_ctx(self, prefix: str = '') -> str:
+ t = self.args[0].type
+ if t == 'BlockDriverState *':
+ return f'bdrv_get_aio_context({prefix}bs)'
+ elif t == 'BdrvChild *':
+ return f'bdrv_get_aio_context({prefix}child->bs)'
+ elif t == 'BlockBackend *':
+ return f'blk_get_aio_context({prefix}blk)'
+ else:
+ return 'qemu_get_aio_context()'
+
def gen_list(self, format: str) -> str:
return ', '.join(format.format_map(arg.__dict__) for arg in self.args)
@@ -262,8 +264,11 @@ typedef struct {struct_name} {{
static void {name}_bh(void *opaque)
{{
{struct_name} *s = opaque;
+ AioContext *ctx = {func.gen_ctx('s->')};
+ aio_context_acquire(ctx);
{func.get_result}{name}({ func.gen_list('s->{name}') });
+ aio_context_release(ctx);
aio_co_wake(s->co);
}}