diff --git a/job.c b/job.c index 926e385ac2..3ef5028751 100644 --- a/job.c +++ b/job.c @@ -588,7 +588,7 @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job)) job->busy = true; real_job_unlock(); job_unlock(); - aio_co_enter(job->aio_context, job->co); + aio_co_wake(job->co); job_lock(); } @@ -615,6 +615,8 @@ void job_enter(Job *job) */ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns) { + AioContext *next_aio_context; + real_job_lock(); if (ns != -1) { timer_mod(&job->sleep_timer, ns); @@ -626,7 +628,20 @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns) qemu_coroutine_yield(); job_lock(); - /* Set by job_enter_cond() before re-entering the coroutine. */ + next_aio_context = job->aio_context; + /* + * Coroutine has resumed, but in the meanwhile the job AioContext + * might have changed via bdrv_try_set_aio_context(), so we need to move + * the coroutine too in the new aiocontext. + */ + while (qemu_get_current_aio_context() != next_aio_context) { + job_unlock(); + aio_co_reschedule_self(next_aio_context); + job_lock(); + next_aio_context = job->aio_context; + } + + /* Set by job_enter_cond_locked() before re-entering the coroutine. */ assert(job->busy); }