block: extract bdrv_drain_poll/bdrv_co_yield_to_drain from bdrv_drain/bdrv_co_drain

Do not call bdrv_drain_recurse twice in bdrv_co_drain.  A small
tweak to the logic in Fam's patch, which is harmless since no
one implements bdrv_drain anyway.  But better get it right.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Paolo Bonzini 2016-04-07 18:33:32 +02:00 committed by Kevin Wolf
parent a72f641407
commit b6e84c97ed

View File

@ -243,18 +243,30 @@ typedef struct {
bool done;
} BdrvCoDrainData;
static void bdrv_drain_poll(BlockDriverState *bs)
{
bool busy = true;
while (busy) {
/* Keep iterating */
bdrv_flush_io_queue(bs);
busy = bdrv_requests_pending(bs);
busy |= aio_poll(bdrv_get_aio_context(bs), busy);
}
}
static void bdrv_co_drain_bh_cb(void *opaque)
{
BdrvCoDrainData *data = opaque;
Coroutine *co = data->co;
qemu_bh_delete(data->bh);
bdrv_drain(data->bs);
bdrv_drain_poll(data->bs);
data->done = true;
qemu_coroutine_enter(co, NULL);
}
void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs)
{
BdrvCoDrainData data;
@ -288,20 +300,19 @@ void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
* not depend on events in other AioContexts. In that case, use
* bdrv_drain_all() instead.
*/
void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
{
bdrv_drain_recurse(bs);
bdrv_co_yield_to_drain(bs);
}
void bdrv_drain(BlockDriverState *bs)
{
bool busy = true;
bdrv_drain_recurse(bs);
if (qemu_in_coroutine()) {
bdrv_co_drain(bs);
return;
}
while (busy) {
/* Keep iterating */
bdrv_flush_io_queue(bs);
busy = bdrv_requests_pending(bs);
busy |= aio_poll(bdrv_get_aio_context(bs), busy);
bdrv_co_yield_to_drain(bs);
} else {
bdrv_drain_poll(bs);
}
}