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
1 changed files with 23 additions and 12 deletions

View File

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