From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41158) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c01IY-0000z4-Iz for qemu-devel@nongnu.org; Fri, 28 Oct 2016 03:09:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1c01IU-0008WH-CR for qemu-devel@nongnu.org; Fri, 28 Oct 2016 03:09:54 -0400 From: Alberto Garcia Date: Fri, 28 Oct 2016 10:08:02 +0300 Message-Id: <3478fbec3323dab23a5e2a2ffb71319ad1bf26e3.1477638050.git.berto@igalia.com> In-Reply-To: References: In-Reply-To: References: Subject: [Qemu-devel] [PATCH v13 01/19] block: Add bdrv_drain_all_{begin, end}() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, Kevin Wolf , Eric Blake , Markus Armbruster , Max Reitz , Alberto Garcia , Paolo Bonzini 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 --- 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 b136c89..d694336 100644 --- a/block/io.c +++ b/block/io.c @@ -275,8 +275,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 busy = true; @@ -300,6 +306,7 @@ void bdrv_drain_all(void) bdrv_parent_drained_begin(bs); bdrv_io_unplugged_begin(bs); bdrv_drain_recurse(bs); + aio_disable_external(aio_context); aio_context_release(aio_context); if (!g_slist_find(aio_ctxs, aio_context)) { @@ -333,17 +340,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); @@ -353,6 +368,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 107c603..301d713 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -338,6 +338,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); int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int count); -- 2.9.3