mirror of https://github.com/xqemu/xqemu.git
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
|
* This function does not flush data to disk, use bdrv_flush_all() for that
|
||||||
* after calling this function.
|
* 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 */
|
/* Always run first iteration so any pending completion BHs run */
|
||||||
bool waited = true;
|
bool waited = true;
|
||||||
|
@ -297,6 +303,7 @@ void bdrv_drain_all(void)
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
bdrv_parent_drained_begin(bs);
|
bdrv_parent_drained_begin(bs);
|
||||||
bdrv_io_unplugged_begin(bs);
|
bdrv_io_unplugged_begin(bs);
|
||||||
|
aio_disable_external(aio_context);
|
||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
|
|
||||||
if (!g_slist_find(aio_ctxs, 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)) {
|
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
aio_enable_external(aio_context);
|
||||||
bdrv_io_unplugged_end(bs);
|
bdrv_io_unplugged_end(bs);
|
||||||
bdrv_parent_drained_end(bs);
|
bdrv_parent_drained_end(bs);
|
||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
g_slist_free(aio_ctxs);
|
|
||||||
|
|
||||||
job = NULL;
|
|
||||||
while ((job = block_job_next(job))) {
|
while ((job = block_job_next(job))) {
|
||||||
AioContext *aio_context = blk_get_aio_context(job->blk);
|
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
|
* 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_close_all(void);
|
||||||
void bdrv_drain(BlockDriverState *bs);
|
void bdrv_drain(BlockDriverState *bs);
|
||||||
void coroutine_fn bdrv_co_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);
|
void bdrv_drain_all(void);
|
||||||
|
|
||||||
#define BDRV_POLL_WHILE(bs, cond) ({ \
|
#define BDRV_POLL_WHILE(bs, cond) ({ \
|
||||||
|
|
Loading…
Reference in New Issue