diff --git a/block/mirror.c b/block/mirror.c index 8888cea952..d409337c4a 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -708,6 +708,8 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); if (!s->dirty_bitmap) { + g_free(s->replaces); + block_job_release(bs); return; } bdrv_set_enable_write_cache(s->target, true); diff --git a/blockjob.c b/blockjob.c index ec46fad2f1..62bb906634 100644 --- a/blockjob.c +++ b/blockjob.c @@ -66,10 +66,7 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, block_job_set_speed(job, speed, &local_err); if (local_err) { - bs->job = NULL; - bdrv_op_unblock_all(bs, job->blocker); - error_free(job->blocker); - g_free(job); + block_job_release(bs); error_propagate(errp, local_err); return NULL; } @@ -77,16 +74,23 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, return job; } +void block_job_release(BlockDriverState *bs) +{ + BlockJob *job = bs->job; + + bs->job = NULL; + bdrv_op_unblock_all(bs, job->blocker); + error_free(job->blocker); + g_free(job); +} + void block_job_completed(BlockJob *job, int ret) { BlockDriverState *bs = job->bs; assert(bs->job == job); job->cb(job->opaque, ret); - bs->job = NULL; - bdrv_op_unblock_all(bs, job->blocker); - error_free(job->blocker); - g_free(job); + block_job_release(bs); } void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 57d8ef13e2..dd9d5e6aad 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -165,6 +165,14 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns); */ void block_job_yield(BlockJob *job); +/** + * block_job_release: + * @bs: The block device. + * + * Release job resources when an error occurred or job completed. + */ +void block_job_release(BlockDriverState *bs); + /** * block_job_completed: * @job: The job being completed.