On 04/07/2017 01:54 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: > > 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, s/rest/remaining/ > qemu_get_aio_context() or qemu_get_current_aio_context(). > > Signed-off-by: Fam Zheng > --- At this point, I'm still more comfortable waiting for Paolo's review. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org