1 From dbdd959063e8f5d13c3051607a0fb7a2e0e178e6 Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Wed, 9 Dec 2015 15:04:57 +0100
4 Subject: [PATCH 14/41] backup: modify job api
6 Introduces a BackupDump function callback and a pause_count
7 for backup_start. For a dump-backup the target parameter
8 can now be NULL so access to target needs to be guarded now.
10 block/backup.c | 82 +++++++++++++++++++++++++++++++----------------
12 include/block/block_int.h | 5 +++
13 3 files changed, 63 insertions(+), 30 deletions(-)
15 diff --git a/block/backup.c b/block/backup.c
16 index 2c05323..f3c0ba3 100644
19 @@ -41,6 +41,7 @@ typedef struct BackupBlockJob {
20 BdrvDirtyBitmap *sync_bitmap;
21 MirrorSyncMode sync_mode;
23 + BackupDumpFunc *dump_cb;
24 BlockdevOnError on_source_error;
25 BlockdevOnError on_target_error;
26 CoRwlock flush_rwlock;
27 @@ -149,12 +150,23 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
31 + int64_t start_sec = start * sectors_per_cluster;
32 if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
33 - ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
34 - bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
36 + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, NULL);
39 + ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
40 + bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
43 - ret = blk_co_pwritev(job->target, start * job->cluster_size,
44 - bounce_qiov.size, &bounce_qiov, 0);
46 + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, bounce_buffer);
49 + ret = blk_co_pwritev(job->target, start * job->cluster_size,
50 + bounce_qiov.size, &bounce_qiov, 0);
54 trace_backup_do_cow_write_fail(job, start, ret);
55 @@ -268,9 +280,11 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job,
57 return block_job_error_action(&job->common, job->on_source_error,
60 + } else if (job->target) {
61 return block_job_error_action(&job->common, job->on_target_error,
64 + return BLOCK_ERROR_ACTION_REPORT;
68 @@ -393,6 +407,7 @@ static void coroutine_fn backup_run(void *opaque)
70 job->done_bitmap = bitmap_new(end);
73 job->before_write.notify = backup_before_write_notify;
74 bdrv_add_before_write_notifier(bs, &job->before_write);
76 @@ -467,7 +482,9 @@ static void coroutine_fn backup_run(void *opaque)
77 qemu_co_rwlock_unlock(&job->flush_rwlock);
78 g_free(job->done_bitmap);
80 - bdrv_op_unblock_all(blk_bs(target), job->common.blocker);
82 + bdrv_op_unblock_all(blk_bs(target), job->common.blocker);
85 data = g_malloc(sizeof(*data));
87 @@ -479,7 +496,9 @@ void backup_start(const char *job_id, BlockDriverState *bs,
88 MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
89 BlockdevOnError on_source_error,
90 BlockdevOnError on_target_error,
91 + BackupDumpFunc *dump_cb,
92 BlockCompletionFunc *cb, void *opaque,
94 BlockJobTxn *txn, Error **errp)
97 @@ -488,7 +507,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
102 + assert(target || dump_cb);
105 error_setg(errp, "Source and target cannot be the same");
106 @@ -501,7 +520,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
110 - if (!bdrv_is_inserted(target)) {
111 + if (target && !bdrv_is_inserted(target)) {
112 error_setg(errp, "Device is not inserted: %s",
113 bdrv_get_device_name(target));
115 @@ -511,7 +530,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
119 - if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
120 + if (target && bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
124 @@ -547,34 +566,43 @@ void backup_start(const char *job_id, BlockDriverState *bs,
128 - job->target = blk_new();
129 - blk_insert_bs(job->target, target);
131 + job->target = blk_new();
132 + blk_insert_bs(job->target, target);
135 + job->dump_cb = dump_cb;
136 job->on_source_error = on_source_error;
137 job->on_target_error = on_target_error;
138 job->sync_mode = sync_mode;
139 job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
142 - /* If there is no backing file on the target, we cannot rely on COW if our
143 - * backup cluster size is smaller than the target cluster size. Even for
144 - * targets with a backing file, try to avoid COW if possible. */
145 - ret = bdrv_get_info(target, &bdi);
146 - if (ret < 0 && !target->backing) {
147 - error_setg_errno(errp, -ret,
148 - "Couldn't determine the cluster size of the target image, "
149 - "which has no backing file");
150 - error_append_hint(errp,
151 - "Aborting, since this may create an unusable destination image\n");
153 - } else if (ret < 0 && target->backing) {
154 - /* Not fatal; just trudge on ahead. */
155 - job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
157 + /* If there is no backing file on the target, we cannot rely on COW if our
158 + * backup cluster size is smaller than the target cluster size. Even for
159 + * targets with a backing file, try to avoid COW if possible. */
160 + ret = bdrv_get_info(target, &bdi);
161 + if (ret < 0 && !target->backing) {
162 + error_setg_errno(errp, -ret,
163 + "Couldn't determine the cluster size of the target image, "
164 + "which has no backing file");
165 + error_append_hint(errp,
166 + "Aborting, since this may create an unusable destination image\n");
168 + } else if (ret < 0 && target->backing) {
169 + /* Not fatal; just trudge on ahead. */
170 + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
172 + job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
175 + bdrv_op_block_all(target, job->common.blocker);
177 - job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
178 + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
181 - bdrv_op_block_all(target, job->common.blocker);
182 + job->common.pause_count = pause_count;
183 job->common.len = len;
184 job->common.co = qemu_coroutine_create(backup_run, job);
185 block_job_txn_add_job(txn, &job->common);
186 diff --git a/blockdev.c b/blockdev.c
187 index 2161400..5e3707d 100644
190 @@ -3277,8 +3277,8 @@ static void do_drive_backup(const char *job_id, const char *device,
193 backup_start(job_id, bs, target_bs, speed, sync, bmap,
194 - on_source_error, on_target_error,
195 - block_job_cb, bs, txn, &local_err);
196 + on_source_error, on_target_error, NULL,
197 + block_job_cb, bs, 0, txn, &local_err);
198 bdrv_unref(target_bs);
199 if (local_err != NULL) {
200 error_propagate(errp, local_err);
201 @@ -3371,7 +3371,7 @@ void do_blockdev_backup(const char *job_id, const char *device,
204 backup_start(job_id, bs, target_bs, speed, sync, NULL, on_source_error,
205 - on_target_error, block_job_cb, bs, txn, &local_err);
206 + on_target_error, NULL, block_job_cb, bs, 0, txn, &local_err);
207 if (local_err != NULL) {
208 error_propagate(errp, local_err);
210 diff --git a/include/block/block_int.h b/include/block/block_int.h
211 index 1e939de..db4650e 100644
212 --- a/include/block/block_int.h
213 +++ b/include/block/block_int.h
216 #define BLOCK_PROBE_BUF_SIZE 512
218 +typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs,
219 + int64_t sector_num, int n_sectors, unsigned char *buf);
221 enum BdrvTrackedRequestType {
224 @@ -767,7 +770,9 @@ void backup_start(const char *job_id, BlockDriverState *bs,
225 MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
226 BlockdevOnError on_source_error,
227 BlockdevOnError on_target_error,
228 + BackupDumpFunc *dump_cb,
229 BlockCompletionFunc *cb, void *opaque,
231 BlockJobTxn *txn, Error **errp);
233 void hmp_drive_add_node(Monitor *mon, const char *optstr);