1 Index: new/block/backup.c
2 ===================================================================
3 --- new.orig/block/backup.c 2014-11-20 07:55:31.000000000 +0100
4 +++ new/block/backup.c 2014-11-20 08:56:23.000000000 +0100
6 BdrvDirtyBitmap *sync_bitmap;
7 MirrorSyncMode sync_mode;
9 + BackupDumpFunc *dump_cb;
10 BlockdevOnError on_source_error;
11 BlockdevOnError on_target_error;
12 CoRwlock flush_rwlock;
17 + int64_t start_sec = start * BACKUP_SECTORS_PER_CLUSTER;
18 if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
19 - ret = bdrv_co_write_zeroes(job->target,
20 - start * BACKUP_SECTORS_PER_CLUSTER,
21 - n, BDRV_REQ_MAY_UNMAP);
23 + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, NULL);
26 + ret = bdrv_co_write_zeroes(job->target, start_sec, n, BDRV_REQ_MAY_UNMAP);
29 - ret = bdrv_co_writev(job->target,
30 - start * BACKUP_SECTORS_PER_CLUSTER, n,
33 + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, bounce_buffer);
36 + ret = bdrv_co_writev(job->target, start_sec, n, &bounce_qiov);
40 trace_backup_do_cow_write_fail(job, start, ret);
43 BackupBlockJob *s = container_of(job, BackupBlockJob, common);
45 - bdrv_iostatus_reset(s->target);
47 + bdrv_iostatus_reset(s->target);
51 static const BlockJobDriver backup_job_driver = {
54 return block_job_error_action(&job->common, job->common.bs,
55 job->on_source_error, true, error);
57 + } else if (job->target) {
58 return block_job_error_action(&job->common, job->target,
59 job->on_target_error, false, error);
61 + return BLOCK_ERROR_ACTION_REPORT;
67 job->bitmap = hbitmap_alloc(end, 0);
69 - bdrv_set_enable_write_cache(target, true);
70 - bdrv_set_on_error(target, on_target_error, on_target_error);
71 - bdrv_iostatus_enable(target);
73 + bdrv_set_enable_write_cache(target, true);
74 + bdrv_set_on_error(target, on_target_error, on_target_error);
75 + bdrv_iostatus_enable(target);
78 bdrv_add_before_write_notifier(bs, &before_write);
82 hbitmap_free(job->bitmap);
84 - bdrv_iostatus_disable(target);
85 - bdrv_op_unblock_all(target, job->common.blocker);
87 + bdrv_iostatus_disable(target);
88 + bdrv_op_unblock_all(target, job->common.blocker);
91 data = g_malloc(sizeof(*data));
93 @@ -456,13 +472,15 @@ for backup_start
94 BdrvDirtyBitmap *sync_bitmap,
95 BlockdevOnError on_source_error,
96 BlockdevOnError on_target_error,
97 + BackupDumpFunc *dump_cb,
98 BlockCompletionFunc *cb, void *opaque,
106 + assert(target || dump_cb);
110 @@ -483,7 +501,7 @@ in backup_start
114 - if (!bdrv_is_inserted(target)) {
115 + if (target && !bdrv_is_inserted(target)) {
116 error_setg(errp, "Device is not inserted: %s",
117 bdrv_get_device_name(target));
119 @@ -493,7 +511,7 @@ in backup_start
123 - if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
124 + if (target && bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
128 @@ -529,14 +547,17 @@ in backup_start
132 - bdrv_op_block_all(target, job->common.blocker);
134 + bdrv_op_block_all(target, job->common.blocker);
136 + job->dump_cb = dump_cb;
137 job->on_source_error = on_source_error;
138 job->on_target_error = on_target_error;
139 job->target = target;
140 job->sync_mode = sync_mode;
141 job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
143 + job->common.pause_count = pause_count;
144 job->common.len = len;
145 job->common.co = qemu_coroutine_create(backup_run);
146 qemu_coroutine_enter(job->common.co, job);
147 Index: new/blockdev.c
148 ===================================================================
149 --- new.orig/blockdev.c 2014-11-20 07:55:31.000000000 +0100
150 +++ new/blockdev.c 2014-11-20 08:48:02.000000000 +0100
151 @@ -2571,8 +2571,8 @@ qmp_drive_backup
154 backup_start(bs, target_bs, speed, sync, bmap,
155 - on_source_error, on_target_error,
156 - block_job_cb, bs, &local_err);
157 + on_source_error, on_target_error, NULL,
158 + block_job_cb, bs, 0, &local_err);
159 if (local_err != NULL) {
160 bdrv_unref(target_bs);
161 error_propagate(errp, local_err);
162 @@ -2633,7 +2633,7 @@ qmp_blockdev_backup
164 bdrv_set_aio_context(target_bs, aio_context);
165 backup_start(bs, target_bs, speed, sync, NULL, on_source_error,
166 - on_target_error, block_job_cb, bs, &local_err);
167 + on_target_error, NULL, block_job_cb, bs, 0, &local_err);
168 if (local_err != NULL) {
169 bdrv_unref(target_bs);
170 error_propagate(errp, local_err);
171 Index: new/include/block/block_int.h
172 ===================================================================
173 --- new.orig/include/block/block_int.h 2014-11-20 07:55:31.000000000 +0100
174 +++ new/include/block/block_int.h 2014-11-20 08:52:59.000000000 +0100
177 #define BLOCK_PROBE_BUF_SIZE 512
179 +typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs,
180 + int64_t sector_num, int n_sectors, unsigned char *buf);
182 typedef struct BdrvTrackedRequest {
183 BlockDriverState *bs;
186 BdrvDirtyBitmap *sync_bitmap,
187 BlockdevOnError on_source_error,
188 BlockdevOnError on_target_error,
189 + BackupDumpFunc *dump_cb,
190 BlockCompletionFunc *cb, void *opaque,
194 void blk_dev_change_media_cb(BlockBackend *blk, bool load);