block: Add bdrv_co_enter()/leave()

Add a pair of functions to temporarily move the current coroutine to the
AioContext of a given BlockDriverState.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20201005155855.256490-13-kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
Kevin Wolf 2020-10-05 17:58:53 +02:00 committed by Markus Armbruster
parent 26b0b698c0
commit e336fd4c4b
2 changed files with 40 additions and 0 deletions

23
block.c
View File

@ -6303,6 +6303,29 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
return bs ? bs->aio_context : qemu_get_aio_context(); return bs ? bs->aio_context : qemu_get_aio_context();
} }
AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs)
{
Coroutine *self = qemu_coroutine_self();
AioContext *old_ctx = qemu_coroutine_get_aio_context(self);
AioContext *new_ctx;
/*
* Increase bs->in_flight to ensure that this operation is completed before
* moving the node to a different AioContext. Read new_ctx only afterwards.
*/
bdrv_inc_in_flight(bs);
new_ctx = bdrv_get_aio_context(bs);
aio_co_reschedule_self(new_ctx);
return old_ctx;
}
void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx)
{
aio_co_reschedule_self(old_ctx);
bdrv_dec_in_flight(bs);
}
void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co) void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
{ {
aio_co_enter(bdrv_get_aio_context(bs), co); aio_co_enter(bdrv_get_aio_context(bs), co);

View File

@ -640,6 +640,23 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
*/ */
AioContext *bdrv_get_aio_context(BlockDriverState *bs); AioContext *bdrv_get_aio_context(BlockDriverState *bs);
/**
* Move the current coroutine to the AioContext of @bs and return the old
* AioContext of the coroutine. Increase bs->in_flight so that draining @bs
* will wait for the operation to proceed until the corresponding
* bdrv_co_leave().
*
* Consequently, you can't call drain inside a bdrv_co_enter/leave() section as
* this will deadlock.
*/
AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs);
/**
* Ends a section started by bdrv_co_enter(). Move the current coroutine back
* to old_ctx and decrease bs->in_flight again.
*/
void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
/** /**
* Transfer control to @co in the aio context of @bs * Transfer control to @co in the aio context of @bs
*/ */