On 04/06/2017 09:25 AM, Fam Zheng wrote: > Coroutine in block layer should always be waken up in bs->aio_context
s/waken up/awakened/ > rather than the "current" context where it is entered. They differ when > the main loop is doing QMP tasks. > > Race conditions happen without this patch, because the wrong context is > acquired in co_schedule_bh_cb, while the entered coroutine works on a > different one. > > Make the block layer explicitly specify a desired context for each created > coroutine. For the rest, always use qemu_get_aio_context(). > > Signed-off-by: Fam Zheng <f...@redhat.com> > --- The meat of the change is here (using an order file to present your diff with the interesting changes first can aid review)... > +++ b/util/qemu-coroutine.c > @@ -43,7 +43,8 @@ static void coroutine_pool_cleanup(Notifier *n, void *value) > } > } > > -Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque) > +Coroutine *qemu_coroutine_create(AioContext *ctx, > + CoroutineEntry *entry, void *opaque) > { > Coroutine *co = NULL; > > @@ -78,6 +79,7 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, > void *opaque) > > co->entry = entry; > co->entry_arg = opaque; > + co->ctx = ctx; > QSIMPLEQ_INIT(&co->co_queue_wakeup); > return co; > } > @@ -107,6 +109,7 @@ void qemu_coroutine_enter(Coroutine *co) > Coroutine *self = qemu_coroutine_self(); > CoroutineAction ret; > > + assert(co->ctx); > trace_qemu_coroutine_enter(self, co, co->entry_arg); > > if (co->caller) { > @@ -115,7 +118,6 @@ void qemu_coroutine_enter(Coroutine *co) > } > > co->caller = self; > - co->ctx = qemu_get_current_aio_context(); Basically, you close the race by assigning co->ctx sooner (during creation, rather than entering the coroutine), where non-block callers still end up with the same context, and block callers now have a chance to provide their desired context up front. Makes for a big patch due to the fallout, but the result seems sane to me. Reviewed-by: Eric Blake <ebl...@redhat.com> -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
signature.asc
Description: OpenPGP digital signature