diff options
author | Max Reitz <mreitz@redhat.com> | 2014-10-24 15:57:33 +0200 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2014-11-03 11:41:48 +0000 |
commit | 345f9e1b04ee18dcb1454dcec49781d5e06ecb60 (patch) | |
tree | 91a3f242d6763f9322bb10d2d78d38c75bf1d0f9 | |
parent | 94054183daffaa41cd77ced9301c01a01027923a (diff) | |
download | hqemu-345f9e1b04ee18dcb1454dcec49781d5e06ecb60.zip hqemu-345f9e1b04ee18dcb1454dcec49781d5e06ecb60.tar.gz |
blockjob: Introduce block_job_complete_sync()
Implement block_job_complete_sync() by doing the exact same thing as
block_job_cancel_sync() does, only with calling block_job_complete()
instead of block_job_cancel().
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 1414159063-25977-5-git-send-email-mreitz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | blockjob.c | 39 | ||||
-rw-r--r-- | include/block/blockjob.h | 15 |
2 files changed, 47 insertions, 7 deletions
@@ -153,7 +153,7 @@ void block_job_iostatus_reset(BlockJob *job) } } -struct BlockCancelData { +struct BlockFinishData { BlockJob *job; BlockCompletionFunc *cb; void *opaque; @@ -161,19 +161,22 @@ struct BlockCancelData { int ret; }; -static void block_job_cancel_cb(void *opaque, int ret) +static void block_job_finish_cb(void *opaque, int ret) { - struct BlockCancelData *data = opaque; + struct BlockFinishData *data = opaque; data->cancelled = block_job_is_cancelled(data->job); data->ret = ret; data->cb(data->opaque, ret); } -int block_job_cancel_sync(BlockJob *job) +static int block_job_finish_sync(BlockJob *job, + void (*finish)(BlockJob *, Error **errp), + Error **errp) { - struct BlockCancelData data; + struct BlockFinishData data; BlockDriverState *bs = job->bs; + Error *local_err = NULL; assert(bs->job == job); @@ -184,15 +187,37 @@ int block_job_cancel_sync(BlockJob *job) data.cb = job->cb; data.opaque = job->opaque; data.ret = -EINPROGRESS; - job->cb = block_job_cancel_cb; + job->cb = block_job_finish_cb; job->opaque = &data; - block_job_cancel(job); + finish(job, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return -EBUSY; + } while (data.ret == -EINPROGRESS) { aio_poll(bdrv_get_aio_context(bs), true); } return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret; } +/* A wrapper around block_job_cancel() taking an Error ** parameter so it may be + * used with block_job_finish_sync() without the need for (rather nasty) + * function pointer casts there. */ +static void block_job_cancel_err(BlockJob *job, Error **errp) +{ + block_job_cancel(job); +} + +int block_job_cancel_sync(BlockJob *job) +{ + return block_job_finish_sync(job, &block_job_cancel_err, NULL); +} + +int block_job_complete_sync(BlockJob *job, Error **errp) +{ + return block_job_finish_sync(job, &block_job_complete, errp); +} + void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns) { assert(job->busy); diff --git a/include/block/blockjob.h b/include/block/blockjob.h index acb399f..ab11a0f 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -273,6 +273,21 @@ bool block_job_is_paused(BlockJob *job); int block_job_cancel_sync(BlockJob *job); /** + * block_job_complete_sync: + * @job: The job to be completed. + * @errp: Error object which may be set by block_job_complete(); this is not + * necessarily set on every error, the job return value has to be + * checked as well. + * + * Synchronously complete the job. The completion callback is called before the + * function returns, unless it is NULL (which is permissible when using this + * function). + * + * Returns the return value from the job. + */ +int block_job_complete_sync(BlockJob *job, Error **errp); + +/** * block_job_iostatus_reset: * @job: The job whose I/O status should be reset. * |