On 08/09/2016 11:28, Fam Zheng wrote: > Right after main_loop ends, we release various things but keep iothread > alive. The latter is not prepared to the sudden change of resources. > > Specifically, after bdrv_close_all(), virtio-scsi dataplane get a > surprise at the empty BlockBackend: > > (gdb) bt > at /usr/src/debug/qemu-2.6.0/hw/scsi/virtio-scsi.c:543 > at /usr/src/debug/qemu-2.6.0/hw/scsi/virtio-scsi.c:577 > > It is because the d->conf.blk->root is set to NULL, then > blk_get_aio_context() returns qemu_aio_context, whereas s->ctx is still > pointing to the iothread: > > hw/scsi/virtio-scsi.c:543: > > if (s->dataplane_started) { > assert(blk_get_aio_context(d->conf.blk) == s->ctx); > } > > To fix this, let's stop iothreads before doing bdrv_close_all(). > > Cc: qemu-sta...@nongnu.org > Signed-off-by: Fam Zheng <f...@redhat.com> > --- > include/sysemu/iothread.h | 1 + > iothread.c | 24 ++++++++++++++++++++---- > vl.c | 2 ++ > 3 files changed, 23 insertions(+), 4 deletions(-) > > diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h > index 2eefea1..68ac2de 100644 > --- a/include/sysemu/iothread.h > +++ b/include/sysemu/iothread.h > @@ -35,5 +35,6 @@ typedef struct { > > char *iothread_get_id(IOThread *iothread); > AioContext *iothread_get_aio_context(IOThread *iothread); > +void iothread_stop_all(void); > > #endif /* IOTHREAD_H */ > diff --git a/iothread.c b/iothread.c > index f183d38..fb08a60 100644 > --- a/iothread.c > +++ b/iothread.c > @@ -54,16 +54,25 @@ static void *iothread_run(void *opaque) > return NULL; > } > > -static void iothread_instance_finalize(Object *obj) > +static int iothread_stop(Object *object, void *opaque) > { > - IOThread *iothread = IOTHREAD(obj); > + IOThread *iothread; > > - if (!iothread->ctx) { > - return; > + iothread = (IOThread *)object_dynamic_cast(object, TYPE_IOTHREAD); > + if (!iothread || !iothread->ctx) { > + return 0; > } > iothread->stopping = true; > aio_notify(iothread->ctx); > qemu_thread_join(&iothread->thread); > + return 0; > +} > + > +static void iothread_instance_finalize(Object *obj) > +{ > + IOThread *iothread = IOTHREAD(obj); > + > + iothread_stop(obj, NULL); > qemu_cond_destroy(&iothread->init_done_cond); > qemu_mutex_destroy(&iothread->init_done_lock); > aio_context_unref(iothread->ctx); > @@ -174,3 +183,10 @@ IOThreadInfoList *qmp_query_iothreads(Error **errp) > object_child_foreach(container, query_one_iothread, &prev); > return head; > } > + > +void iothread_stop_all(void) > +{ > + Object *container = object_get_objects_root(); > + > + object_child_foreach(container, iothread_stop, NULL); > +} > diff --git a/vl.c b/vl.c > index ee557a1..6a218ce 100644 > --- a/vl.c > +++ b/vl.c > @@ -121,6 +121,7 @@ int main(int argc, char **argv) > #include "crypto/init.h" > #include "sysemu/replay.h" > #include "qapi/qmp/qerror.h" > +#include "sysemu/iothread.h" > > #define MAX_VIRTIO_CONSOLES 1 > #define MAX_SCLP_CONSOLES 1 > @@ -4616,6 +4617,7 @@ int main(int argc, char **argv, char **envp) > trace_init_vcpu_events(); > main_loop(); > replay_disable_events(); > + iothread_stop_all(); > > bdrv_close_all(); > pause_all_vcpus(); >
Reviewed-by: Paolo Bonzini <pbonz...@redhat.com> Paolo