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 <berto@igalia.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
ad0e90a682
commit
c0778f6693
27
block/io.c
27
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
|
||||
*
|
||||
|
@ -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) ({ \
|
||||
|
Loading…
Reference in New Issue
Block a user