1 From c46139b295f9edffd43a12e7f029fce4f9b2ea46 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/48] 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 | 118 +++++++++++++++++++++++++++++-----------------
11 block/replication.c | 3 +-
13 include/block/block_int.h | 5 ++
14 4 files changed, 83 insertions(+), 47 deletions(-)
16 diff --git a/block/backup.c b/block/backup.c
17 index a4fb288..fe4ce7f 100644
20 @@ -36,6 +36,7 @@ typedef struct BackupBlockJob {
21 BdrvDirtyBitmap *sync_bitmap;
22 MirrorSyncMode sync_mode;
24 + BackupDumpFunc *dump_cb;
25 BlockdevOnError on_source_error;
26 BlockdevOnError on_target_error;
27 CoRwlock flush_rwlock;
28 @@ -145,13 +146,24 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
32 + int64_t start_sec = start * sectors_per_cluster;
33 if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
34 - ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
35 - bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
37 + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, NULL);
40 + ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
41 + bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
44 - ret = blk_co_pwritev(job->target, start * job->cluster_size,
45 - bounce_qiov.size, &bounce_qiov,
46 - job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
48 + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, bounce_buffer);
51 + ret = blk_co_pwritev(job->target, start * job->cluster_size,
52 + bounce_qiov.size, &bounce_qiov,
53 + job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
57 trace_backup_do_cow_write_fail(job, start, ret);
58 @@ -246,6 +258,8 @@ static void backup_abort(BlockJob *job)
59 static void backup_clean(BlockJob *job)
61 BackupBlockJob *s = container_of(job, BackupBlockJob, common);
67 @@ -330,9 +344,11 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job,
69 return block_job_error_action(&job->common, job->on_source_error,
72 + } else if (job->target) {
73 return block_job_error_action(&job->common, job->on_target_error,
76 + return BLOCK_ERROR_ACTION_REPORT;
80 @@ -453,6 +469,7 @@ static void coroutine_fn backup_run(void *opaque)
82 job->done_bitmap = bitmap_new(end);
85 job->before_write.notify = backup_before_write_notify;
86 bdrv_add_before_write_notifier(bs, &job->before_write);
88 @@ -557,7 +574,9 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
89 BlockdevOnError on_source_error,
90 BlockdevOnError on_target_error,
92 + BackupDumpFunc *dump_cb,
93 BlockCompletionFunc *cb, void *opaque,
95 BlockJobTxn *txn, Error **errp)
98 @@ -566,7 +585,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
103 + assert(target || dump_cb);
106 error_setg(errp, "Source and target cannot be the same");
107 @@ -579,13 +598,13 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
111 - if (!bdrv_is_inserted(target)) {
112 + if (target && !bdrv_is_inserted(target)) {
113 error_setg(errp, "Device is not inserted: %s",
114 bdrv_get_device_name(target));
118 - if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
119 + if (target && compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
120 error_setg(errp, "Compression is not supported for this drive %s",
121 bdrv_get_device_name(target));
123 @@ -595,7 +614,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
127 - if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
128 + if (target && bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
132 @@ -635,15 +654,18 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
136 - /* The target must match the source in size, so no resize here either */
137 - job->target = blk_new(BLK_PERM_WRITE,
138 - BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
139 - BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
140 - ret = blk_insert_bs(job->target, target, errp);
144 + /* The target must match the source in size, so no resize here either */
145 + job->target = blk_new(BLK_PERM_WRITE,
146 + BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
147 + BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
148 + ret = blk_insert_bs(job->target, target, errp);
154 + job->dump_cb = dump_cb;
155 job->on_source_error = on_source_error;
156 job->on_target_error = on_target_error;
157 job->sync_mode = sync_mode;
158 @@ -651,36 +673,44 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
160 job->compress = compress;
162 - /* If there is no backing file on the target, we cannot rely on COW if our
163 - * backup cluster size is smaller than the target cluster size. Even for
164 - * targets with a backing file, try to avoid COW if possible. */
165 - ret = bdrv_get_info(target, &bdi);
166 - if (ret == -ENOTSUP && !target->backing) {
167 - /* Cluster size is not defined */
168 - error_report("WARNING: The target block device doesn't provide "
169 - "information about the block size and it doesn't have a "
170 - "backing file. The default block size of %u bytes is "
171 - "used. If the actual block size of the target exceeds "
172 - "this default, the backup may be unusable",
173 - BACKUP_CLUSTER_SIZE_DEFAULT);
174 - job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
175 - } else if (ret < 0 && !target->backing) {
176 - error_setg_errno(errp, -ret,
177 - "Couldn't determine the cluster size of the target image, "
178 - "which has no backing file");
179 - error_append_hint(errp,
180 - "Aborting, since this may create an unusable destination image\n");
182 - } else if (ret < 0 && target->backing) {
183 - /* Not fatal; just trudge on ahead. */
184 - job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
186 + /* If there is no backing file on the target, we cannot rely on COW if our
187 + * backup cluster size is smaller than the target cluster size. Even for
188 + * targets with a backing file, try to avoid COW if possible. */
189 + ret = bdrv_get_info(target, &bdi);
190 + if (ret == -ENOTSUP && !target->backing) {
191 + /* Cluster size is not defined */
192 + error_report("WARNING: The target block device doesn't provide "
193 + "information about the block size and it doesn't have a "
194 + "backing file. The default block size of %u bytes is "
195 + "used. If the actual block size of the target exceeds "
196 + "this default, the backup may be unusable",
197 + BACKUP_CLUSTER_SIZE_DEFAULT);
198 + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
199 + } else if (ret < 0 && !target->backing) {
200 + error_setg_errno(errp, -ret,
201 + "Couldn't determine the cluster size of the target image, "
202 + "which has no backing file");
203 + error_append_hint(errp,
204 + "Aborting, since this may create an unusable destination image\n");
206 + } else if (ret < 0 && target->backing) {
207 + /* Not fatal; just trudge on ahead. */
208 + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
210 + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
213 - job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
214 + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
217 - /* Required permissions are already taken with target's blk_new() */
218 - block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
221 + /* Required permissions are already taken with target's blk_new() */
222 + block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
225 + job->common.pause_count = pause_count;
227 job->common.len = len;
228 block_job_txn_add_job(txn, &job->common);
230 diff --git a/block/replication.c b/block/replication.c
231 index bf3c395..60c6524 100644
232 --- a/block/replication.c
233 +++ b/block/replication.c
234 @@ -531,7 +531,8 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
235 0, MIRROR_SYNC_MODE_NONE, NULL, false,
236 BLOCKDEV_ON_ERROR_REPORT,
237 BLOCKDEV_ON_ERROR_REPORT, BLOCK_JOB_INTERNAL,
238 - backup_job_completed, bs, NULL, &local_err);
240 + backup_job_completed, bs, 0, NULL, &local_err);
242 error_propagate(errp, local_err);
243 backup_job_cleanup(bs);
244 diff --git a/blockdev.c b/blockdev.c
245 index 040c152..bb3fc5b 100644
248 @@ -3273,7 +3273,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
249 job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
250 backup->sync, bmap, backup->compress,
251 backup->on_source_error, backup->on_target_error,
252 - BLOCK_JOB_DEFAULT, NULL, NULL, txn, &local_err);
253 + BLOCK_JOB_DEFAULT, NULL, NULL, NULL, 0, txn, &local_err);
254 bdrv_unref(target_bs);
255 if (local_err != NULL) {
256 error_propagate(errp, local_err);
257 @@ -3352,7 +3352,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
258 job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
259 backup->sync, NULL, backup->compress,
260 backup->on_source_error, backup->on_target_error,
261 - BLOCK_JOB_DEFAULT, NULL, NULL, txn, &local_err);
262 + BLOCK_JOB_DEFAULT, NULL, NULL, NULL, 0, txn, &local_err);
263 if (local_err != NULL) {
264 error_propagate(errp, local_err);
266 diff --git a/include/block/block_int.h b/include/block/block_int.h
267 index 59400bd..ec65581 100644
268 --- a/include/block/block_int.h
269 +++ b/include/block/block_int.h
272 #define BLOCK_PROBE_BUF_SIZE 512
274 +typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs,
275 + int64_t sector_num, int n_sectors, unsigned char *buf);
277 enum BdrvTrackedRequestType {
280 @@ -877,7 +880,9 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
281 BlockdevOnError on_source_error,
282 BlockdevOnError on_target_error,
284 + BackupDumpFunc *dump_cb,
285 BlockCompletionFunc *cb, void *opaque,
287 BlockJobTxn *txn, Error **errp);
289 void hmp_drive_add_node(Monitor *mon, const char *optstr);