Message ID | 1465928228-1184-4-git-send-email-stefanha@redhat.com |
---|---|
State | New |
Headers | show |
On Tue, 06/14 19:17, Stefan Hajnoczi wrote: > > +static void block_job_attached_aio_context(AioContext *new_context, > + void *opaque) > +{ > + BlockJob *job = opaque; > + > + if (job->driver->attached_aio_context) { > + job->driver->attached_aio_context(job, new_context); > + } > + > + block_job_resume(job); > +} > + > +static void block_job_detach_aio_context(void *opaque) > +{ > + BlockJob *job = opaque; > + > + /* In case the job terminates during aio_poll()... */ > + block_job_ref(job); > + > + block_job_pause(job); > + > + if (!job->paused) { > + /* If job is !job->busy this kicks it into the next pause point. */ > + block_job_enter(job); > + } > + while (!job->paused && !job->completed) { > + aio_poll(blk_get_aio_context(job->blk), true); For the complete part, we should do it like block_job_finish_sync: while (!job->completed) { aio_poll(job->deferred_to_main_loop ? qemu_get_aio_context() : blk_get_aio_context(job->blk), true); } > + } > + > + block_job_unref(job); > +} > + Fam
On Wed, Jun 15, 2016 at 05:05:28PM +0800, Fam Zheng wrote: > On Tue, 06/14 19:17, Stefan Hajnoczi wrote: > > > > +static void block_job_attached_aio_context(AioContext *new_context, > > + void *opaque) > > +{ > > + BlockJob *job = opaque; > > + > > + if (job->driver->attached_aio_context) { > > + job->driver->attached_aio_context(job, new_context); > > + } > > + > > + block_job_resume(job); > > +} > > + > > +static void block_job_detach_aio_context(void *opaque) > > +{ > > + BlockJob *job = opaque; > > + > > + /* In case the job terminates during aio_poll()... */ > > + block_job_ref(job); > > + > > + block_job_pause(job); > > + > > + if (!job->paused) { > > + /* If job is !job->busy this kicks it into the next pause point. */ > > + block_job_enter(job); > > + } > > + while (!job->paused && !job->completed) { > > + aio_poll(blk_get_aio_context(job->blk), true); > > For the complete part, we should do it like block_job_finish_sync: > > while (!job->completed) { > aio_poll(job->deferred_to_main_loop ? qemu_get_aio_context() : > blk_get_aio_context(job->blk), > true); > } Will fix in v5.
diff --git a/blockjob.c b/blockjob.c index 1a383d1..a5ce982 100644 --- a/blockjob.c +++ b/blockjob.c @@ -60,6 +60,38 @@ BlockJob *block_job_next(BlockJob *job) return QLIST_NEXT(job, job_list); } +static void block_job_attached_aio_context(AioContext *new_context, + void *opaque) +{ + BlockJob *job = opaque; + + if (job->driver->attached_aio_context) { + job->driver->attached_aio_context(job, new_context); + } + + block_job_resume(job); +} + +static void block_job_detach_aio_context(void *opaque) +{ + BlockJob *job = opaque; + + /* In case the job terminates during aio_poll()... */ + block_job_ref(job); + + block_job_pause(job); + + if (!job->paused) { + /* If job is !job->busy this kicks it into the next pause point. */ + block_job_enter(job); + } + while (!job->paused && !job->completed) { + aio_poll(blk_get_aio_context(job->blk), true); + } + + block_job_unref(job); +} + void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, int64_t speed, BlockCompletionFunc *cb, void *opaque, Error **errp) @@ -92,6 +124,9 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, QLIST_INSERT_HEAD(&block_jobs, job, job_list); + blk_add_aio_context_notifier(blk, block_job_attached_aio_context, + block_job_detach_aio_context, job); + /* Only set speed when necessary to avoid NotSupported error */ if (speed != 0) { Error *local_err = NULL; @@ -117,6 +152,9 @@ void block_job_unref(BlockJob *job) BlockDriverState *bs = blk_bs(job->blk); bs->job = NULL; bdrv_op_unblock_all(bs, job->blocker); + blk_remove_aio_context_notifier(job->blk, + block_job_attached_aio_context, + block_job_detach_aio_context, job); blk_unref(job->blk); error_free(job->blocker); g_free(job->id); diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 154c48b..98550bc 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -84,6 +84,13 @@ typedef struct BlockJobDriver { * should be restarted from this callback. */ void (*resume)(BlockJob *job); + + /* + * If the callback is not NULL, it will be invoked before the job is + * resumed in a new AioContext. This is the place to move any resources + * besides job->blk to the new AioContext. + */ + void (*attached_aio_context)(BlockJob *job, AioContext *new_context); } BlockJobDriver; /**
Block jobs that use additional BDSes or event loop resources need a callback to get their affairs in order when the AioContext is switched. Simple block jobs don't need an attach callback, they automatically work thanks to the generic attach/detach notifiers that this patch adds. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> --- blockjob.c | 38 ++++++++++++++++++++++++++++++++++++++ include/block/blockjob.h | 7 +++++++ 2 files changed, 45 insertions(+)