On Tue, Mar 13, 2012 at 2:22 AM, Paolo Bonzini <pbonz...@redhat.com> wrote: > From: Zhi Yong Wu <wu...@linux.vnet.ibm.com> > > Signed-off-by: Zhi Yong Wu <wu...@linux.vnet.ibm.com> > [ Iterate until all block devices have processed all requests, > add comments. - Paolo ] > Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> > --- > block.c | 21 ++++++++++++++++++++- > 1 files changed, 20 insertions(+), 1 deletions(-) > > diff --git a/block.c b/block.c > index dac62a1..0d769a6 100644 > --- a/block.c > +++ b/block.c > @@ -858,12 +858,31 @@ void bdrv_close_all(void) > * > * This function does not flush data to disk, use bdrv_flush_all() for that > * after calling this function. > + * > + * Note that completion of an asynchronous I/O operation can trigger any > + * number of other I/O operations on other devices---for example a coroutine > + * can be arbitrarily complex and a constant flow of I/O to multiple devices > + * can come until the coroutine is complete. Because of this, it is not > + * possible to drain a single device's I/O queue. > */ > void bdrv_drain_all(void) > { > BlockDriverState *bs; > + bool busy; > > - qemu_aio_flush(); > + do { > + busy = qemu_aio_wait(); > + > + /* FIXME: We do not have timer support here, so this is effectively > + * a busy wait. Maybe we can temporarily disable I/O throttling, after flush is completed, enable it again. But this perhaps affects other guest. > + */ > + QTAILQ_FOREACH(bs, &bdrv_states, list) { > + if (!qemu_co_queue_empty(&bs->throttled_reqs)) { > + qemu_co_queue_restart_all(&bs->throttled_reqs); > + busy = true; > + } > + } > + } while (busy); > > /* If requests are still pending there is a bug somewhere */ > QTAILQ_FOREACH(bs, &bdrv_states, list) { > -- > 1.7.7.6 > >
-- Regards, Zhi Yong Wu