On 01/04/2016 11:46, Fam Zheng wrote: > + > +static void bdrv_co_drain_bh_cb(void *opaque) > +{ > + BdrvCoDrainData *data = opaque; > + Coroutine *co = data->co; > + > + bdrv_drain(data->bs); > + data->done = true; > + qemu_coroutine_enter(co, NULL); > +} > + > +static void coroutine_fn bdrv_co_drain(BlockDriverState *bs) > +{ > + QEMUBH *bh; > + BdrvCoDrainData data; > + > + assert(qemu_in_coroutine()); > + data = (BdrvCoDrainData) { > + .co = qemu_coroutine_self(), > + .bs = bs, > + .done = false, > + }; > + bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_drain_bh_cb, &data), > + qemu_bh_schedule(bh); > + > + do { > + qemu_coroutine_yield(); > + } while (!data.done);
The loop and "done" is not necessary. Also, > + qemu_bh_delete(bh); this can be moved to bdrv_co_drain_bh_cb before bdrv_drain, so that the bottom half doesn't slow down the event loop until bdrv_drain completes. Paolo > +}