Message ID | 20170419144219.20371-12-pbonzini@redhat.com |
---|---|
State | New |
Headers | show |
On Wed, Apr 19, 2017 at 04:42:19PM +0200, Paolo Bonzini wrote: > All block jobs are using block_job_defer_to_main_loop as the final > step just before the coroutine terminates. At this point, > block_job_enter should do nothing, but currently it restarts > the freed coroutine. > > Now, the job->co states should probably be changed to an enum > (e.g. BEFORE_START, STARTED, YIELDED, COMPLETED) subsuming > block_job_started, job->deferred_to_main_loop and job->busy. > For now, this patch eliminates the problematic reenter by > removing the reset of job->deferred_to_main_loop (which served > no purpose, as far as I could see) and checking the flag in > block_job_enter. The defer_to_main_loop API was originally written as a utility that could be called multiple times, not just during the final phase of the block job. In practice we only use it to complete the block job. I suggest integrating it more deeply into blockjob.c so that all jobs automatically invoke it once and only once. There should be a BlockJobDriver.main_loop_finalize() callback and the defer_to_main_loop shouldn't be callable outside blockjob.c to prevent misuse.
On Wed, Apr 19, 2017 at 04:42:19PM +0200, Paolo Bonzini wrote: > All block jobs are using block_job_defer_to_main_loop as the final > step just before the coroutine terminates. At this point, > block_job_enter should do nothing, but currently it restarts > the freed coroutine. > > Now, the job->co states should probably be changed to an enum > (e.g. BEFORE_START, STARTED, YIELDED, COMPLETED) subsuming > block_job_started, job->deferred_to_main_loop and job->busy. > For now, this patch eliminates the problematic reenter by > removing the reset of job->deferred_to_main_loop (which served > no purpose, as far as I could see) and checking the flag in > block_job_enter. > > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > blockjob.c | 10 ++++++++-- > include/block/blockjob_int.h | 3 ++- > 2 files changed, 10 insertions(+), 3 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/blockjob.c b/blockjob.c index e8b6247..295478d 100644 --- a/blockjob.c +++ b/blockjob.c @@ -771,7 +771,14 @@ void block_job_resume_all(void) void block_job_enter(BlockJob *job) { - if (job->co && !job->busy) { + if (!block_job_started(job)) { + return; + } + if (job->deferred_to_main_loop) { + return; + } + + if (!job->busy) { bdrv_coroutine_enter(blk_bs(job->blk), job->co); } } @@ -899,7 +906,6 @@ static void block_job_defer_to_main_loop_bh(void *opaque) aio_context_acquire(aio_context); } - data->job->deferred_to_main_loop = false; data->fn(data->job, data->opaque); if (aio_context != data->aio_context) { diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h index cbf984b..a9751a7 100644 --- a/include/block/blockjob_int.h +++ b/include/block/blockjob_int.h @@ -241,7 +241,8 @@ typedef void BlockJobDeferToMainLoopFn(BlockJob *job, void *opaque); * @fn: The function to run in the main loop * @opaque: The opaque value that is passed to @fn * - * Execute a given function in the main loop with the BlockDriverState + * This function must be called by the main job coroutine just before it + * returns. @fn is executed in the main loop with the BlockDriverState * AioContext acquired. Block jobs must call bdrv_unref(), bdrv_close(), and * anything that uses bdrv_drain_all() in the main loop. *
All block jobs are using block_job_defer_to_main_loop as the final step just before the coroutine terminates. At this point, block_job_enter should do nothing, but currently it restarts the freed coroutine. Now, the job->co states should probably be changed to an enum (e.g. BEFORE_START, STARTED, YIELDED, COMPLETED) subsuming block_job_started, job->deferred_to_main_loop and job->busy. For now, this patch eliminates the problematic reenter by removing the reset of job->deferred_to_main_loop (which served no purpose, as far as I could see) and checking the flag in block_job_enter. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- blockjob.c | 10 ++++++++-- include/block/blockjob_int.h | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-)