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>
This commit is contained in:
		
							parent
							
								
									94054183da
								
							
						
					
					
						commit
						345f9e1b04
					
				
							
								
								
									
										39
									
								
								blockjob.c
								
								
								
								
							
							
						
						
									
										39
									
								
								blockjob.c
								
								
								
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -272,6 +272,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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue