On Fri, Apr 07, 2017 at 02:54:13PM +0800, Fam Zheng wrote: > Coroutine in block layer should always be waken up in bs->aio_context > 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: > > main loop iothread > ----------------------------------------------------------------------- > blockdev_snapshot > aio_context_acquire(bs->ctx) > bdrv_flush(bs) > bdrv_co_flush(bs) > ... > qemu_coroutine_yield(co) > BDRV_POLL_WHILE() > aio_context_release(bs->ctx) > aio_context_acquire(bs->ctx) > ... > aio_co_wake(co) > aio_poll(qemu_aio_context) ... > co_schedule_bh_cb() ... > qemu_coroutine_enter(co) ... > /* (A) bdrv_co_flush(bs) /* (B) I/O on bs */ > continues... */ > aio_context_release(bs->ctx) > > Both (A) and (B) can access resources protected by bs->ctx, but (A) is > not thread-safe. > > Make the block layer explicitly specify a desired context for the > entered coroutine. For the rest callers, stick to the old behavior, > qemu_get_aio_context() or qemu_get_current_aio_context(). I wasn't expecting the patch to touch so many places. If a coroutine can be permanently associated with an AioContext then there's no need to keep assigning co->ctx on each qemu_coroutine_enter(). I don't know about this one. Paolo is the best person to review it since he's most familiar with the recent Coroutine/AioContext changes. Stefan