diff options
Diffstat (limited to 'block/mirror.c')
-rw-r--r-- | block/mirror.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/block/mirror.c b/block/mirror.c index 80fd3c7469..075384a9cf 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -44,6 +44,7 @@ typedef struct MirrorBlockJob { /* Used to block operations on the drive-mirror-replace target */ Error *replace_blocker; bool is_none_mode; + BlockMirrorBackingMode backing_mode; BlockdevOnError on_source_error, on_target_error; bool synced; bool should_complete; @@ -157,8 +158,7 @@ static void mirror_read_complete(void *opaque, int ret) return; } blk_aio_pwritev(s->target, op->sector_num * BDRV_SECTOR_SIZE, &op->qiov, - op->nb_sectors * BDRV_SECTOR_SIZE, - mirror_write_complete, op); + 0, mirror_write_complete, op); } static inline void mirror_clip_sectors(MirrorBlockJob *s, @@ -186,8 +186,9 @@ static int mirror_cow_align(MirrorBlockJob *s, need_cow |= !test_bit((*sector_num + *nb_sectors - 1) / chunk_sectors, s->cow_bitmap); if (need_cow) { - bdrv_round_to_clusters(blk_bs(s->target), *sector_num, *nb_sectors, - &align_sector_num, &align_nb_sectors); + bdrv_round_sectors_to_clusters(blk_bs(s->target), *sector_num, + *nb_sectors, &align_sector_num, + &align_nb_sectors); } if (align_nb_sectors > max_sectors) { @@ -274,8 +275,7 @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num, s->sectors_in_flight += nb_sectors; trace_mirror_one_iteration(s, sector_num, nb_sectors); - blk_aio_preadv(source, sector_num * BDRV_SECTOR_SIZE, &op->qiov, - nb_sectors * BDRV_SECTOR_SIZE, + blk_aio_preadv(source, sector_num * BDRV_SECTOR_SIZE, &op->qiov, 0, mirror_read_complete, op); return ret; } @@ -386,8 +386,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) } else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) { int64_t target_sector_num; int target_nb_sectors; - bdrv_round_to_clusters(blk_bs(s->target), sector_num, io_sectors, - &target_sector_num, &target_nb_sectors); + bdrv_round_sectors_to_clusters(blk_bs(s->target), sector_num, + io_sectors, &target_sector_num, + &target_nb_sectors); if (target_sector_num == sector_num && target_nb_sectors == io_sectors) { mirror_method = ret & BDRV_BLOCK_ZERO ? @@ -742,20 +743,26 @@ static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp) static void mirror_complete(BlockJob *job, Error **errp) { MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); - Error *local_err = NULL; - int ret; + BlockDriverState *src, *target; + + src = blk_bs(job->blk); + target = blk_bs(s->target); - ret = bdrv_open_backing_file(blk_bs(s->target), NULL, "backing", - &local_err); - if (ret < 0) { - error_propagate(errp, local_err); - return; - } if (!s->synced) { error_setg(errp, QERR_BLOCK_JOB_NOT_READY, job->id); return; } + if (s->backing_mode == MIRROR_OPEN_BACKING_CHAIN) { + int ret; + + assert(!target->backing); + ret = bdrv_open_backing_file(target, NULL, "backing", errp); + if (ret < 0) { + return; + } + } + /* check the target bs is not blocked and block all operations on it */ if (s->replaces) { AioContext *replace_aio_context; @@ -777,6 +784,13 @@ static void mirror_complete(BlockJob *job, Error **errp) aio_context_release(replace_aio_context); } + if (s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) { + BlockDriverState *backing = s->is_none_mode ? src : s->base; + if (backing_bs(target) != backing) { + bdrv_set_backing_hd(target, backing); + } + } + s->should_complete = true; block_job_enter(&s->common); } @@ -799,6 +813,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, const char *replaces, int64_t speed, uint32_t granularity, int64_t buf_size, + BlockMirrorBackingMode backing_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, @@ -836,6 +851,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, s->on_source_error = on_source_error; s->on_target_error = on_target_error; s->is_none_mode = is_none_mode; + s->backing_mode = backing_mode; s->base = base; s->granularity = granularity; s->buf_size = ROUND_UP(buf_size, granularity); @@ -859,7 +875,8 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, void mirror_start(BlockDriverState *bs, BlockDriverState *target, const char *replaces, int64_t speed, uint32_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockdevOnError on_source_error, + MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, + BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, BlockCompletionFunc *cb, @@ -875,7 +892,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target, is_none_mode = mode == MIRROR_SYNC_MODE_NONE; base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL; mirror_start_job(bs, target, replaces, - speed, granularity, buf_size, + speed, granularity, buf_size, backing_mode, on_source_error, on_target_error, unmap, cb, opaque, errp, &mirror_job_driver, is_none_mode, base); } @@ -922,7 +939,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base, } } - mirror_start_job(bs, base, NULL, speed, 0, 0, + mirror_start_job(bs, base, NULL, speed, 0, 0, MIRROR_LEAVE_BACKING_CHAIN, on_error, on_error, false, cb, opaque, &local_err, &commit_active_job_driver, false, base); if (local_err) { |