From c0778f6693213d0d6bfa7bee8045374a798db750 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Fri, 28 Oct 2016 10:08:02 +0300 Subject: [PATCH] block: Add bdrv_drain_all_{begin,end}() bdrv_drain_all() doesn't allow the caller to do anything after all pending requests have been completed but before block jobs are resumed. This patch splits bdrv_drain_all() into _begin() and _end() for that purpose. It also adds aio_{disable,enable}_external() calls to disable external clients in the meantime. An important restriction of this split is that no new block jobs or BlockDriverStates can be created between the bdrv_drain_all_begin() and bdrv_drain_all_end() calls. This is not a concern now because we'll only be using this in bdrv_reopen_multiple(), but it must be dealt with if we ever have other uses cases in the future. Signed-off-by: Alberto Garcia Cc: Paolo Bonzini Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/io.c | 27 ++++++++++++++++++++++++--- include/block/block.h | 2 ++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/block/io.c b/block/io.c index be0d862ca6..37749b680a 100644 --- a/block/io.c +++ b/block/io.c @@ -273,8 +273,14 @@ void bdrv_drain(BlockDriverState *bs) * * This function does not flush data to disk, use bdrv_flush_all() for that * after calling this function. + * + * This pauses all block jobs and disables external clients. It must + * be paired with bdrv_drain_all_end(). + * + * NOTE: no new block jobs or BlockDriverStates can be created between + * the bdrv_drain_all_begin() and bdrv_drain_all_end() calls. */ -void bdrv_drain_all(void) +void bdrv_drain_all_begin(void) { /* Always run first iteration so any pending completion BHs run */ bool waited = true; @@ -297,6 +303,7 @@ void bdrv_drain_all(void) aio_context_acquire(aio_context); bdrv_parent_drained_begin(bs); bdrv_io_unplugged_begin(bs); + aio_disable_external(aio_context); aio_context_release(aio_context); if (!g_slist_find(aio_ctxs, aio_context)) { @@ -326,17 +333,25 @@ void bdrv_drain_all(void) } } + g_slist_free(aio_ctxs); +} + +void bdrv_drain_all_end(void) +{ + BlockDriverState *bs; + BdrvNextIterator it; + BlockJob *job = NULL; + for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); + aio_enable_external(aio_context); bdrv_io_unplugged_end(bs); bdrv_parent_drained_end(bs); aio_context_release(aio_context); } - g_slist_free(aio_ctxs); - job = NULL; while ((job = block_job_next(job))) { AioContext *aio_context = blk_get_aio_context(job->blk); @@ -346,6 +361,12 @@ void bdrv_drain_all(void) } } +void bdrv_drain_all(void) +{ + bdrv_drain_all_begin(); + bdrv_drain_all_end(); +} + /** * Remove an active request from the tracked requests list * diff --git a/include/block/block.h b/include/block/block.h index b7dc7d54ae..b81a3e35ce 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -332,6 +332,8 @@ int bdrv_flush_all(void); void bdrv_close_all(void); void bdrv_drain(BlockDriverState *bs); void coroutine_fn bdrv_co_drain(BlockDriverState *bs); +void bdrv_drain_all_begin(void); +void bdrv_drain_all_end(void); void bdrv_drain_all(void); #define BDRV_POLL_WHILE(bs, cond) ({ \ -- 2.11.4.GIT