mirror of https://gitee.com/openkylin/qemu.git
blockjob: add AioContext attached callback
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> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Fam Zheng <famz@redhat.com> Message-id: 1466096189-6477-7-git-send-email-stefanha@redhat.com
This commit is contained in:
parent
e8a095dadb
commit
463e0be101
38
blockjob.c
38
blockjob.c
|
@ -71,6 +71,38 @@ static AioContext *block_job_get_aio_context(BlockJob *job)
|
|||
blk_get_aio_context(job->blk);
|
||||
}
|
||||
|
||||
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(block_job_get_aio_context(job), true);
|
||||
}
|
||||
|
||||
block_job_unref(job);
|
||||
}
|
||||
|
||||
void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
|
||||
int64_t speed, BlockCompletionFunc *cb,
|
||||
void *opaque, Error **errp)
|
||||
|
@ -103,6 +135,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;
|
||||
|
@ -128,6 +163,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);
|
||||
|
|
|
@ -84,6 +84,13 @@ typedef struct BlockJobDriver {
|
|||
* should be restarted from this callback.
|
||||
*/
|
||||
void coroutine_fn (*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;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue