On Thu, Apr 12, 2012 at 8:00 PM, 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 file changed, 20 insertions(+), 1 deletion(-) > > diff --git a/block.c b/block.c > index 4b96654..33efa95 100644 > --- a/block.c > +++ b/block.c > @@ -863,12 +863,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 can come until the > + * coroutine is complete. Because of this, it is not possible to have a > + * function 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(); When bdrv_drain_all is invoked, if bs->tracked_requests has some pending I/O requests, only qemu_aio_wait is called here, not qemu_aio_flush() to restart them in bs->tracked_requests. It will cause assert about bs->tracked_requests. > + > + /* FIXME: We do not have timer support here, so this is effectively > + * a busy wait. > + */ > + 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.9.3 > > >
-- Regards, Zhi Yong Wu