1893f7ebaSPaolo Bonzini /* 2893f7ebaSPaolo Bonzini * Image mirroring 3893f7ebaSPaolo Bonzini * 4893f7ebaSPaolo Bonzini * Copyright Red Hat, Inc. 2012 5893f7ebaSPaolo Bonzini * 6893f7ebaSPaolo Bonzini * Authors: 7893f7ebaSPaolo Bonzini * Paolo Bonzini <pbonzini@redhat.com> 8893f7ebaSPaolo Bonzini * 9893f7ebaSPaolo Bonzini * This work is licensed under the terms of the GNU LGPL, version 2 or later. 10893f7ebaSPaolo Bonzini * See the COPYING.LIB file in the top-level directory. 11893f7ebaSPaolo Bonzini * 12893f7ebaSPaolo Bonzini */ 13893f7ebaSPaolo Bonzini 14893f7ebaSPaolo Bonzini #include "trace.h" 15737e150eSPaolo Bonzini #include "block/blockjob.h" 16737e150eSPaolo Bonzini #include "block/block_int.h" 17893f7ebaSPaolo Bonzini #include "qemu/ratelimit.h" 18b812f671SPaolo Bonzini #include "qemu/bitmap.h" 19893f7ebaSPaolo Bonzini 20893f7ebaSPaolo Bonzini #define SLICE_TIME 100000000ULL /* ns */ 21893f7ebaSPaolo Bonzini 22893f7ebaSPaolo Bonzini typedef struct MirrorBlockJob { 23893f7ebaSPaolo Bonzini BlockJob common; 24893f7ebaSPaolo Bonzini RateLimit limit; 25893f7ebaSPaolo Bonzini BlockDriverState *target; 26893f7ebaSPaolo Bonzini MirrorSyncMode mode; 27b952b558SPaolo Bonzini BlockdevOnError on_source_error, on_target_error; 28d63ffd87SPaolo Bonzini bool synced; 29d63ffd87SPaolo Bonzini bool should_complete; 30893f7ebaSPaolo Bonzini int64_t sector_num; 31*eee13dfeSPaolo Bonzini int64_t granularity; 32b812f671SPaolo Bonzini size_t buf_size; 33b812f671SPaolo Bonzini unsigned long *cow_bitmap; 348f0720ecSPaolo Bonzini HBitmapIter hbi; 35893f7ebaSPaolo Bonzini uint8_t *buf; 36893f7ebaSPaolo Bonzini } MirrorBlockJob; 37893f7ebaSPaolo Bonzini 38b952b558SPaolo Bonzini static BlockErrorAction mirror_error_action(MirrorBlockJob *s, bool read, 39b952b558SPaolo Bonzini int error) 40b952b558SPaolo Bonzini { 41b952b558SPaolo Bonzini s->synced = false; 42b952b558SPaolo Bonzini if (read) { 43b952b558SPaolo Bonzini return block_job_error_action(&s->common, s->common.bs, 44b952b558SPaolo Bonzini s->on_source_error, true, error); 45b952b558SPaolo Bonzini } else { 46b952b558SPaolo Bonzini return block_job_error_action(&s->common, s->target, 47b952b558SPaolo Bonzini s->on_target_error, false, error); 48b952b558SPaolo Bonzini } 49b952b558SPaolo Bonzini } 50b952b558SPaolo Bonzini 51b952b558SPaolo Bonzini static int coroutine_fn mirror_iteration(MirrorBlockJob *s, 52b952b558SPaolo Bonzini BlockErrorAction *p_action) 53893f7ebaSPaolo Bonzini { 54893f7ebaSPaolo Bonzini BlockDriverState *source = s->common.bs; 55893f7ebaSPaolo Bonzini BlockDriverState *target = s->target; 56893f7ebaSPaolo Bonzini QEMUIOVector qiov; 57*eee13dfeSPaolo Bonzini int ret, nb_sectors, sectors_per_chunk; 58b812f671SPaolo Bonzini int64_t end, sector_num, chunk_num; 59893f7ebaSPaolo Bonzini struct iovec iov; 60893f7ebaSPaolo Bonzini 618f0720ecSPaolo Bonzini s->sector_num = hbitmap_iter_next(&s->hbi); 628f0720ecSPaolo Bonzini if (s->sector_num < 0) { 638f0720ecSPaolo Bonzini bdrv_dirty_iter_init(source, &s->hbi); 648f0720ecSPaolo Bonzini s->sector_num = hbitmap_iter_next(&s->hbi); 658f0720ecSPaolo Bonzini trace_mirror_restart_iter(s, bdrv_get_dirty_count(source)); 668f0720ecSPaolo Bonzini assert(s->sector_num >= 0); 678f0720ecSPaolo Bonzini } 688f0720ecSPaolo Bonzini 69b812f671SPaolo Bonzini /* If we have no backing file yet in the destination, and the cluster size 70b812f671SPaolo Bonzini * is very large, we need to do COW ourselves. The first time a cluster is 71b812f671SPaolo Bonzini * copied, copy it entirely. 72b812f671SPaolo Bonzini * 73*eee13dfeSPaolo Bonzini * Because both the granularity and the cluster size are powers of two, the 74*eee13dfeSPaolo Bonzini * number of sectors to copy cannot exceed one cluster. 75b812f671SPaolo Bonzini */ 76b812f671SPaolo Bonzini sector_num = s->sector_num; 77*eee13dfeSPaolo Bonzini sectors_per_chunk = nb_sectors = s->granularity >> BDRV_SECTOR_BITS; 78*eee13dfeSPaolo Bonzini chunk_num = sector_num / sectors_per_chunk; 79b812f671SPaolo Bonzini if (s->cow_bitmap && !test_bit(chunk_num, s->cow_bitmap)) { 80b812f671SPaolo Bonzini trace_mirror_cow(s, sector_num); 81b812f671SPaolo Bonzini bdrv_round_to_clusters(s->target, 82*eee13dfeSPaolo Bonzini sector_num, sectors_per_chunk, 83b812f671SPaolo Bonzini §or_num, &nb_sectors); 84b812f671SPaolo Bonzini } 85b812f671SPaolo Bonzini 86893f7ebaSPaolo Bonzini end = s->common.len >> BDRV_SECTOR_BITS; 87b812f671SPaolo Bonzini nb_sectors = MIN(nb_sectors, end - sector_num); 88b812f671SPaolo Bonzini bdrv_reset_dirty(source, sector_num, nb_sectors); 89893f7ebaSPaolo Bonzini 90893f7ebaSPaolo Bonzini /* Copy the dirty cluster. */ 91893f7ebaSPaolo Bonzini iov.iov_base = s->buf; 92893f7ebaSPaolo Bonzini iov.iov_len = nb_sectors * 512; 93893f7ebaSPaolo Bonzini qemu_iovec_init_external(&qiov, &iov, 1); 94893f7ebaSPaolo Bonzini 95b812f671SPaolo Bonzini trace_mirror_one_iteration(s, sector_num, nb_sectors); 96b812f671SPaolo Bonzini ret = bdrv_co_readv(source, sector_num, nb_sectors, &qiov); 97893f7ebaSPaolo Bonzini if (ret < 0) { 98b952b558SPaolo Bonzini *p_action = mirror_error_action(s, true, -ret); 99b952b558SPaolo Bonzini goto fail; 100893f7ebaSPaolo Bonzini } 101b812f671SPaolo Bonzini ret = bdrv_co_writev(target, sector_num, nb_sectors, &qiov); 102b952b558SPaolo Bonzini if (ret < 0) { 103b952b558SPaolo Bonzini *p_action = mirror_error_action(s, false, -ret); 104b952b558SPaolo Bonzini s->synced = false; 105b952b558SPaolo Bonzini goto fail; 106b952b558SPaolo Bonzini } 107b812f671SPaolo Bonzini if (s->cow_bitmap) { 108*eee13dfeSPaolo Bonzini bitmap_set(s->cow_bitmap, sector_num / sectors_per_chunk, 109*eee13dfeSPaolo Bonzini nb_sectors / sectors_per_chunk); 110b812f671SPaolo Bonzini } 111b952b558SPaolo Bonzini return 0; 112b952b558SPaolo Bonzini 113b952b558SPaolo Bonzini fail: 114b952b558SPaolo Bonzini /* Try again later. */ 115b812f671SPaolo Bonzini bdrv_set_dirty(source, sector_num, nb_sectors); 116b952b558SPaolo Bonzini return ret; 117893f7ebaSPaolo Bonzini } 118893f7ebaSPaolo Bonzini 119893f7ebaSPaolo Bonzini static void coroutine_fn mirror_run(void *opaque) 120893f7ebaSPaolo Bonzini { 121893f7ebaSPaolo Bonzini MirrorBlockJob *s = opaque; 122893f7ebaSPaolo Bonzini BlockDriverState *bs = s->common.bs; 123*eee13dfeSPaolo Bonzini int64_t sector_num, end, sectors_per_chunk, length; 124b812f671SPaolo Bonzini BlockDriverInfo bdi; 125b812f671SPaolo Bonzini char backing_filename[1024]; 126893f7ebaSPaolo Bonzini int ret = 0; 127893f7ebaSPaolo Bonzini int n; 128893f7ebaSPaolo Bonzini 129893f7ebaSPaolo Bonzini if (block_job_is_cancelled(&s->common)) { 130893f7ebaSPaolo Bonzini goto immediate_exit; 131893f7ebaSPaolo Bonzini } 132893f7ebaSPaolo Bonzini 133893f7ebaSPaolo Bonzini s->common.len = bdrv_getlength(bs); 134893f7ebaSPaolo Bonzini if (s->common.len < 0) { 135893f7ebaSPaolo Bonzini block_job_completed(&s->common, s->common.len); 136893f7ebaSPaolo Bonzini return; 137893f7ebaSPaolo Bonzini } 138893f7ebaSPaolo Bonzini 139b812f671SPaolo Bonzini /* If we have no backing file yet in the destination, we cannot let 140b812f671SPaolo Bonzini * the destination do COW. Instead, we copy sectors around the 141b812f671SPaolo Bonzini * dirty data if needed. We need a bitmap to do that. 142b812f671SPaolo Bonzini */ 143b812f671SPaolo Bonzini bdrv_get_backing_filename(s->target, backing_filename, 144b812f671SPaolo Bonzini sizeof(backing_filename)); 145b812f671SPaolo Bonzini if (backing_filename[0] && !s->target->backing_hd) { 146b812f671SPaolo Bonzini bdrv_get_info(s->target, &bdi); 147*eee13dfeSPaolo Bonzini if (s->granularity < bdi.cluster_size) { 148b812f671SPaolo Bonzini s->buf_size = bdi.cluster_size; 149*eee13dfeSPaolo Bonzini length = (bdrv_getlength(bs) + s->granularity - 1) / s->granularity; 150b812f671SPaolo Bonzini s->cow_bitmap = bitmap_new(length); 151b812f671SPaolo Bonzini } 152b812f671SPaolo Bonzini } 153b812f671SPaolo Bonzini 154893f7ebaSPaolo Bonzini end = s->common.len >> BDRV_SECTOR_BITS; 155b812f671SPaolo Bonzini s->buf = qemu_blockalign(bs, s->buf_size); 156*eee13dfeSPaolo Bonzini sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS; 157893f7ebaSPaolo Bonzini 158893f7ebaSPaolo Bonzini if (s->mode != MIRROR_SYNC_MODE_NONE) { 159893f7ebaSPaolo Bonzini /* First part, loop on the sectors and initialize the dirty bitmap. */ 160893f7ebaSPaolo Bonzini BlockDriverState *base; 161893f7ebaSPaolo Bonzini base = s->mode == MIRROR_SYNC_MODE_FULL ? NULL : bs->backing_hd; 162893f7ebaSPaolo Bonzini for (sector_num = 0; sector_num < end; ) { 163*eee13dfeSPaolo Bonzini int64_t next = (sector_num | (sectors_per_chunk - 1)) + 1; 164893f7ebaSPaolo Bonzini ret = bdrv_co_is_allocated_above(bs, base, 165893f7ebaSPaolo Bonzini sector_num, next - sector_num, &n); 166893f7ebaSPaolo Bonzini 167893f7ebaSPaolo Bonzini if (ret < 0) { 168893f7ebaSPaolo Bonzini goto immediate_exit; 169893f7ebaSPaolo Bonzini } 170893f7ebaSPaolo Bonzini 171893f7ebaSPaolo Bonzini assert(n > 0); 172893f7ebaSPaolo Bonzini if (ret == 1) { 173893f7ebaSPaolo Bonzini bdrv_set_dirty(bs, sector_num, n); 174893f7ebaSPaolo Bonzini sector_num = next; 175893f7ebaSPaolo Bonzini } else { 176893f7ebaSPaolo Bonzini sector_num += n; 177893f7ebaSPaolo Bonzini } 178893f7ebaSPaolo Bonzini } 179893f7ebaSPaolo Bonzini } 180893f7ebaSPaolo Bonzini 1818f0720ecSPaolo Bonzini bdrv_dirty_iter_init(bs, &s->hbi); 182893f7ebaSPaolo Bonzini for (;;) { 183893f7ebaSPaolo Bonzini uint64_t delay_ns; 184893f7ebaSPaolo Bonzini int64_t cnt; 185893f7ebaSPaolo Bonzini bool should_complete; 186893f7ebaSPaolo Bonzini 187893f7ebaSPaolo Bonzini cnt = bdrv_get_dirty_count(bs); 188893f7ebaSPaolo Bonzini if (cnt != 0) { 189b952b558SPaolo Bonzini BlockErrorAction action = BDRV_ACTION_REPORT; 190b952b558SPaolo Bonzini ret = mirror_iteration(s, &action); 191b952b558SPaolo Bonzini if (ret < 0 && action == BDRV_ACTION_REPORT) { 192893f7ebaSPaolo Bonzini goto immediate_exit; 193893f7ebaSPaolo Bonzini } 194893f7ebaSPaolo Bonzini cnt = bdrv_get_dirty_count(bs); 195893f7ebaSPaolo Bonzini } 196893f7ebaSPaolo Bonzini 197893f7ebaSPaolo Bonzini should_complete = false; 198893f7ebaSPaolo Bonzini if (cnt == 0) { 199893f7ebaSPaolo Bonzini trace_mirror_before_flush(s); 200893f7ebaSPaolo Bonzini ret = bdrv_flush(s->target); 201893f7ebaSPaolo Bonzini if (ret < 0) { 202b952b558SPaolo Bonzini if (mirror_error_action(s, false, -ret) == BDRV_ACTION_REPORT) { 203893f7ebaSPaolo Bonzini goto immediate_exit; 204893f7ebaSPaolo Bonzini } 205b952b558SPaolo Bonzini } else { 206893f7ebaSPaolo Bonzini /* We're out of the streaming phase. From now on, if the job 207893f7ebaSPaolo Bonzini * is cancelled we will actually complete all pending I/O and 208893f7ebaSPaolo Bonzini * report completion. This way, block-job-cancel will leave 209893f7ebaSPaolo Bonzini * the target in a consistent state. 210893f7ebaSPaolo Bonzini */ 211893f7ebaSPaolo Bonzini s->common.offset = end * BDRV_SECTOR_SIZE; 212d63ffd87SPaolo Bonzini if (!s->synced) { 213d63ffd87SPaolo Bonzini block_job_ready(&s->common); 214d63ffd87SPaolo Bonzini s->synced = true; 215d63ffd87SPaolo Bonzini } 216d63ffd87SPaolo Bonzini 217d63ffd87SPaolo Bonzini should_complete = s->should_complete || 218d63ffd87SPaolo Bonzini block_job_is_cancelled(&s->common); 219893f7ebaSPaolo Bonzini cnt = bdrv_get_dirty_count(bs); 220893f7ebaSPaolo Bonzini } 221b952b558SPaolo Bonzini } 222893f7ebaSPaolo Bonzini 223893f7ebaSPaolo Bonzini if (cnt == 0 && should_complete) { 224893f7ebaSPaolo Bonzini /* The dirty bitmap is not updated while operations are pending. 225893f7ebaSPaolo Bonzini * If we're about to exit, wait for pending operations before 226893f7ebaSPaolo Bonzini * calling bdrv_get_dirty_count(bs), or we may exit while the 227893f7ebaSPaolo Bonzini * source has dirty data to copy! 228893f7ebaSPaolo Bonzini * 229893f7ebaSPaolo Bonzini * Note that I/O can be submitted by the guest while 230893f7ebaSPaolo Bonzini * mirror_populate runs. 231893f7ebaSPaolo Bonzini */ 232893f7ebaSPaolo Bonzini trace_mirror_before_drain(s, cnt); 233893f7ebaSPaolo Bonzini bdrv_drain_all(); 234893f7ebaSPaolo Bonzini cnt = bdrv_get_dirty_count(bs); 235893f7ebaSPaolo Bonzini } 236893f7ebaSPaolo Bonzini 237893f7ebaSPaolo Bonzini ret = 0; 238d63ffd87SPaolo Bonzini trace_mirror_before_sleep(s, cnt, s->synced); 239d63ffd87SPaolo Bonzini if (!s->synced) { 240893f7ebaSPaolo Bonzini /* Publish progress */ 241acc906c6SPaolo Bonzini s->common.offset = (end - cnt) * BDRV_SECTOR_SIZE; 242893f7ebaSPaolo Bonzini 243893f7ebaSPaolo Bonzini if (s->common.speed) { 244*eee13dfeSPaolo Bonzini delay_ns = ratelimit_calculate_delay(&s->limit, sectors_per_chunk); 245893f7ebaSPaolo Bonzini } else { 246893f7ebaSPaolo Bonzini delay_ns = 0; 247893f7ebaSPaolo Bonzini } 248893f7ebaSPaolo Bonzini 249893f7ebaSPaolo Bonzini /* Note that even when no rate limit is applied we need to yield 250c57b6656SKevin Wolf * with no pending I/O here so that bdrv_drain_all() returns. 251893f7ebaSPaolo Bonzini */ 252893f7ebaSPaolo Bonzini block_job_sleep_ns(&s->common, rt_clock, delay_ns); 253893f7ebaSPaolo Bonzini if (block_job_is_cancelled(&s->common)) { 254893f7ebaSPaolo Bonzini break; 255893f7ebaSPaolo Bonzini } 256893f7ebaSPaolo Bonzini } else if (!should_complete) { 257893f7ebaSPaolo Bonzini delay_ns = (cnt == 0 ? SLICE_TIME : 0); 258893f7ebaSPaolo Bonzini block_job_sleep_ns(&s->common, rt_clock, delay_ns); 259893f7ebaSPaolo Bonzini } else if (cnt == 0) { 260893f7ebaSPaolo Bonzini /* The two disks are in sync. Exit and report successful 261893f7ebaSPaolo Bonzini * completion. 262893f7ebaSPaolo Bonzini */ 263893f7ebaSPaolo Bonzini assert(QLIST_EMPTY(&bs->tracked_requests)); 264893f7ebaSPaolo Bonzini s->common.cancelled = false; 265893f7ebaSPaolo Bonzini break; 266893f7ebaSPaolo Bonzini } 267893f7ebaSPaolo Bonzini } 268893f7ebaSPaolo Bonzini 269893f7ebaSPaolo Bonzini immediate_exit: 2707191bf31SMarkus Armbruster qemu_vfree(s->buf); 271b812f671SPaolo Bonzini g_free(s->cow_bitmap); 27250717e94SPaolo Bonzini bdrv_set_dirty_tracking(bs, 0); 273b952b558SPaolo Bonzini bdrv_iostatus_disable(s->target); 274d63ffd87SPaolo Bonzini if (s->should_complete && ret == 0) { 275d63ffd87SPaolo Bonzini if (bdrv_get_flags(s->target) != bdrv_get_flags(s->common.bs)) { 276d63ffd87SPaolo Bonzini bdrv_reopen(s->target, bdrv_get_flags(s->common.bs), NULL); 277d63ffd87SPaolo Bonzini } 278d63ffd87SPaolo Bonzini bdrv_swap(s->target, s->common.bs); 279d63ffd87SPaolo Bonzini } 280893f7ebaSPaolo Bonzini bdrv_close(s->target); 281893f7ebaSPaolo Bonzini bdrv_delete(s->target); 282893f7ebaSPaolo Bonzini block_job_completed(&s->common, ret); 283893f7ebaSPaolo Bonzini } 284893f7ebaSPaolo Bonzini 285893f7ebaSPaolo Bonzini static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp) 286893f7ebaSPaolo Bonzini { 287893f7ebaSPaolo Bonzini MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); 288893f7ebaSPaolo Bonzini 289893f7ebaSPaolo Bonzini if (speed < 0) { 290893f7ebaSPaolo Bonzini error_set(errp, QERR_INVALID_PARAMETER, "speed"); 291893f7ebaSPaolo Bonzini return; 292893f7ebaSPaolo Bonzini } 293893f7ebaSPaolo Bonzini ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME); 294893f7ebaSPaolo Bonzini } 295893f7ebaSPaolo Bonzini 296b952b558SPaolo Bonzini static void mirror_iostatus_reset(BlockJob *job) 297b952b558SPaolo Bonzini { 298b952b558SPaolo Bonzini MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); 299b952b558SPaolo Bonzini 300b952b558SPaolo Bonzini bdrv_iostatus_reset(s->target); 301b952b558SPaolo Bonzini } 302b952b558SPaolo Bonzini 303d63ffd87SPaolo Bonzini static void mirror_complete(BlockJob *job, Error **errp) 304d63ffd87SPaolo Bonzini { 305d63ffd87SPaolo Bonzini MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); 306d63ffd87SPaolo Bonzini int ret; 307d63ffd87SPaolo Bonzini 308d63ffd87SPaolo Bonzini ret = bdrv_open_backing_file(s->target); 309d63ffd87SPaolo Bonzini if (ret < 0) { 310d63ffd87SPaolo Bonzini char backing_filename[PATH_MAX]; 311d63ffd87SPaolo Bonzini bdrv_get_full_backing_filename(s->target, backing_filename, 312d63ffd87SPaolo Bonzini sizeof(backing_filename)); 313d63ffd87SPaolo Bonzini error_set(errp, QERR_OPEN_FILE_FAILED, backing_filename); 314d63ffd87SPaolo Bonzini return; 315d63ffd87SPaolo Bonzini } 316d63ffd87SPaolo Bonzini if (!s->synced) { 317d63ffd87SPaolo Bonzini error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name); 318d63ffd87SPaolo Bonzini return; 319d63ffd87SPaolo Bonzini } 320d63ffd87SPaolo Bonzini 321d63ffd87SPaolo Bonzini s->should_complete = true; 322d63ffd87SPaolo Bonzini block_job_resume(job); 323d63ffd87SPaolo Bonzini } 324d63ffd87SPaolo Bonzini 325893f7ebaSPaolo Bonzini static BlockJobType mirror_job_type = { 326893f7ebaSPaolo Bonzini .instance_size = sizeof(MirrorBlockJob), 327893f7ebaSPaolo Bonzini .job_type = "mirror", 328893f7ebaSPaolo Bonzini .set_speed = mirror_set_speed, 329b952b558SPaolo Bonzini .iostatus_reset= mirror_iostatus_reset, 330d63ffd87SPaolo Bonzini .complete = mirror_complete, 331893f7ebaSPaolo Bonzini }; 332893f7ebaSPaolo Bonzini 333893f7ebaSPaolo Bonzini void mirror_start(BlockDriverState *bs, BlockDriverState *target, 334*eee13dfeSPaolo Bonzini int64_t speed, int64_t granularity, MirrorSyncMode mode, 335b952b558SPaolo Bonzini BlockdevOnError on_source_error, 336b952b558SPaolo Bonzini BlockdevOnError on_target_error, 337893f7ebaSPaolo Bonzini BlockDriverCompletionFunc *cb, 338893f7ebaSPaolo Bonzini void *opaque, Error **errp) 339893f7ebaSPaolo Bonzini { 340893f7ebaSPaolo Bonzini MirrorBlockJob *s; 341893f7ebaSPaolo Bonzini 342*eee13dfeSPaolo Bonzini if (granularity == 0) { 343*eee13dfeSPaolo Bonzini /* Choose the default granularity based on the target file's cluster 344*eee13dfeSPaolo Bonzini * size, clamped between 4k and 64k. */ 345*eee13dfeSPaolo Bonzini BlockDriverInfo bdi; 346*eee13dfeSPaolo Bonzini if (bdrv_get_info(target, &bdi) >= 0 && bdi.cluster_size != 0) { 347*eee13dfeSPaolo Bonzini granularity = MAX(4096, bdi.cluster_size); 348*eee13dfeSPaolo Bonzini granularity = MIN(65536, granularity); 349*eee13dfeSPaolo Bonzini } else { 350*eee13dfeSPaolo Bonzini granularity = 65536; 351*eee13dfeSPaolo Bonzini } 352*eee13dfeSPaolo Bonzini } 353*eee13dfeSPaolo Bonzini 354*eee13dfeSPaolo Bonzini assert ((granularity & (granularity - 1)) == 0); 355*eee13dfeSPaolo Bonzini 356b952b558SPaolo Bonzini if ((on_source_error == BLOCKDEV_ON_ERROR_STOP || 357b952b558SPaolo Bonzini on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) && 358b952b558SPaolo Bonzini !bdrv_iostatus_is_enabled(bs)) { 359b952b558SPaolo Bonzini error_set(errp, QERR_INVALID_PARAMETER, "on-source-error"); 360b952b558SPaolo Bonzini return; 361b952b558SPaolo Bonzini } 362b952b558SPaolo Bonzini 363893f7ebaSPaolo Bonzini s = block_job_create(&mirror_job_type, bs, speed, cb, opaque, errp); 364893f7ebaSPaolo Bonzini if (!s) { 365893f7ebaSPaolo Bonzini return; 366893f7ebaSPaolo Bonzini } 367893f7ebaSPaolo Bonzini 368b952b558SPaolo Bonzini s->on_source_error = on_source_error; 369b952b558SPaolo Bonzini s->on_target_error = on_target_error; 370893f7ebaSPaolo Bonzini s->target = target; 371893f7ebaSPaolo Bonzini s->mode = mode; 372*eee13dfeSPaolo Bonzini s->granularity = granularity; 373*eee13dfeSPaolo Bonzini s->buf_size = granularity; 374b812f671SPaolo Bonzini 375*eee13dfeSPaolo Bonzini bdrv_set_dirty_tracking(bs, granularity); 376893f7ebaSPaolo Bonzini bdrv_set_enable_write_cache(s->target, true); 377b952b558SPaolo Bonzini bdrv_set_on_error(s->target, on_target_error, on_target_error); 378b952b558SPaolo Bonzini bdrv_iostatus_enable(s->target); 379893f7ebaSPaolo Bonzini s->common.co = qemu_coroutine_create(mirror_run); 380893f7ebaSPaolo Bonzini trace_mirror_start(bs, s, s->common.co, opaque); 381893f7ebaSPaolo Bonzini qemu_coroutine_enter(s->common.co, s); 382893f7ebaSPaolo Bonzini } 383