]>
Commit | Line | Data |
---|---|---|
68a30562 | 1 | From dbdd959063e8f5d13c3051607a0fb7a2e0e178e6 Mon Sep 17 00:00:00 2001 |
ca0fe5f5 WB |
2 | From: Wolfgang Bumiller <w.bumiller@proxmox.com> |
3 | Date: Wed, 9 Dec 2015 15:04:57 +0100 | |
68a30562 | 4 | Subject: [PATCH 14/41] backup: modify job api |
ca0fe5f5 WB |
5 | |
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. | |
9 | --- | |
68a30562 | 10 | block/backup.c | 82 +++++++++++++++++++++++++++++++---------------- |
b07d35a5 TL |
11 | blockdev.c | 6 ++-- |
12 | include/block/block_int.h | 5 +++ | |
68a30562 | 13 | 3 files changed, 63 insertions(+), 30 deletions(-) |
ca0fe5f5 WB |
14 | |
15 | diff --git a/block/backup.c b/block/backup.c | |
68a30562 | 16 | index 2c05323..f3c0ba3 100644 |
ca0fe5f5 WB |
17 | --- a/block/backup.c |
18 | +++ b/block/backup.c | |
6fb04df7 | 19 | @@ -41,6 +41,7 @@ typedef struct BackupBlockJob { |
ca0fe5f5 WB |
20 | BdrvDirtyBitmap *sync_bitmap; |
21 | MirrorSyncMode sync_mode; | |
22 | RateLimit limit; | |
23 | + BackupDumpFunc *dump_cb; | |
24 | BlockdevOnError on_source_error; | |
25 | BlockdevOnError on_target_error; | |
26 | CoRwlock flush_rwlock; | |
68a30562 | 27 | @@ -149,12 +150,23 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, |
ca0fe5f5 WB |
28 | goto out; |
29 | } | |
30 | ||
b07d35a5 | 31 | + int64_t start_sec = start * sectors_per_cluster; |
ca0fe5f5 | 32 | if (buffer_is_zero(iov.iov_base, iov.iov_len)) { |
68a30562 WB |
33 | - ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size, |
34 | - bounce_qiov.size, BDRV_REQ_MAY_UNMAP); | |
ca0fe5f5 WB |
35 | + if (job->dump_cb) { |
36 | + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, NULL); | |
37 | + } | |
38 | + if (job->target) { | |
68a30562 WB |
39 | + ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size, |
40 | + bounce_qiov.size, BDRV_REQ_MAY_UNMAP); | |
ca0fe5f5 WB |
41 | + } |
42 | } else { | |
68a30562 WB |
43 | - ret = blk_co_pwritev(job->target, start * job->cluster_size, |
44 | - bounce_qiov.size, &bounce_qiov, 0); | |
ca0fe5f5 WB |
45 | + if (job->dump_cb) { |
46 | + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, bounce_buffer); | |
47 | + } | |
48 | + if (job->target) { | |
68a30562 WB |
49 | + ret = blk_co_pwritev(job->target, start * job->cluster_size, |
50 | + bounce_qiov.size, &bounce_qiov, 0); | |
ca0fe5f5 WB |
51 | + } |
52 | } | |
53 | if (ret < 0) { | |
54 | trace_backup_do_cow_write_fail(job, start, ret); | |
68a30562 | 55 | @@ -268,9 +280,11 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job, |
ca0fe5f5 | 56 | if (read) { |
68a30562 WB |
57 | return block_job_error_action(&job->common, job->on_source_error, |
58 | true, error); | |
ca0fe5f5 WB |
59 | - } else { |
60 | + } else if (job->target) { | |
68a30562 WB |
61 | return block_job_error_action(&job->common, job->on_target_error, |
62 | false, error); | |
ca0fe5f5 WB |
63 | + } else { |
64 | + return BLOCK_ERROR_ACTION_REPORT; | |
65 | } | |
66 | } | |
67 | ||
68a30562 | 68 | @@ -393,6 +407,7 @@ static void coroutine_fn backup_run(void *opaque) |
ca0fe5f5 | 69 | |
b07d35a5 | 70 | job->done_bitmap = bitmap_new(end); |
ca0fe5f5 | 71 | |
68a30562 WB |
72 | + |
73 | job->before_write.notify = backup_before_write_notify; | |
74 | bdrv_add_before_write_notifier(bs, &job->before_write); | |
ca0fe5f5 | 75 | |
68a30562 | 76 | @@ -467,7 +482,9 @@ static void coroutine_fn backup_run(void *opaque) |
ca0fe5f5 | 77 | qemu_co_rwlock_unlock(&job->flush_rwlock); |
b07d35a5 | 78 | g_free(job->done_bitmap); |
ca0fe5f5 | 79 | |
68a30562 | 80 | - bdrv_op_unblock_all(blk_bs(target), job->common.blocker); |
ca0fe5f5 | 81 | + if (target) { |
68a30562 WB |
82 | + bdrv_op_unblock_all(blk_bs(target), job->common.blocker); |
83 | + } | |
ca0fe5f5 WB |
84 | |
85 | data = g_malloc(sizeof(*data)); | |
86 | data->ret = ret; | |
68a30562 WB |
87 | @@ -479,7 +496,9 @@ void backup_start(const char *job_id, BlockDriverState *bs, |
88 | MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap, | |
ca0fe5f5 WB |
89 | BlockdevOnError on_source_error, |
90 | BlockdevOnError on_target_error, | |
91 | + BackupDumpFunc *dump_cb, | |
92 | BlockCompletionFunc *cb, void *opaque, | |
93 | + int pause_count, | |
94 | BlockJobTxn *txn, Error **errp) | |
95 | { | |
96 | int64_t len; | |
68a30562 | 97 | @@ -488,7 +507,7 @@ void backup_start(const char *job_id, BlockDriverState *bs, |
b07d35a5 | 98 | int ret; |
ca0fe5f5 WB |
99 | |
100 | assert(bs); | |
101 | - assert(target); | |
102 | + assert(target || dump_cb); | |
ca0fe5f5 WB |
103 | |
104 | if (bs == target) { | |
68a30562 WB |
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, | |
ca0fe5f5 WB |
107 | return; |
108 | } | |
109 | ||
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)); | |
114 | return; | |
68a30562 | 115 | @@ -511,7 +530,7 @@ void backup_start(const char *job_id, BlockDriverState *bs, |
ca0fe5f5 WB |
116 | return; |
117 | } | |
118 | ||
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)) { | |
121 | return; | |
122 | } | |
123 | ||
68a30562 | 124 | @@ -547,34 +566,43 @@ void backup_start(const char *job_id, BlockDriverState *bs, |
ca0fe5f5 WB |
125 | goto error; |
126 | } | |
127 | ||
68a30562 WB |
128 | - job->target = blk_new(); |
129 | - blk_insert_bs(job->target, target); | |
130 | + if (target) { | |
131 | + job->target = blk_new(); | |
132 | + blk_insert_bs(job->target, target); | |
133 | + } | |
134 | ||
ca0fe5f5 WB |
135 | + job->dump_cb = dump_cb; |
136 | job->on_source_error = on_source_error; | |
137 | job->on_target_error = on_target_error; | |
68a30562 | 138 | job->sync_mode = sync_mode; |
ca0fe5f5 WB |
139 | job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ? |
140 | sync_bitmap : NULL; | |
b07d35a5 TL |
141 | |
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. */ | |
68a30562 | 145 | - ret = bdrv_get_info(target, &bdi); |
b07d35a5 TL |
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"); | |
152 | - goto error; | |
153 | - } else if (ret < 0 && target->backing) { | |
154 | - /* Not fatal; just trudge on ahead. */ | |
155 | - job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; | |
156 | + if (target) { | |
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. */ | |
68a30562 | 160 | + ret = bdrv_get_info(target, &bdi); |
b07d35a5 TL |
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"); | |
167 | + goto error; | |
168 | + } else if (ret < 0 && target->backing) { | |
169 | + /* Not fatal; just trudge on ahead. */ | |
170 | + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; | |
171 | + } else { | |
172 | + job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size); | |
173 | + } | |
174 | + | |
175 | + bdrv_op_block_all(target, job->common.blocker); | |
176 | } else { | |
177 | - job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size); | |
178 | + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; | |
179 | } | |
180 | ||
181 | - bdrv_op_block_all(target, job->common.blocker); | |
ca0fe5f5 WB |
182 | + job->common.pause_count = pause_count; |
183 | job->common.len = len; | |
68a30562 | 184 | job->common.co = qemu_coroutine_create(backup_run, job); |
ca0fe5f5 WB |
185 | block_job_txn_add_job(txn, &job->common); |
186 | diff --git a/blockdev.c b/blockdev.c | |
68a30562 | 187 | index 2161400..5e3707d 100644 |
ca0fe5f5 WB |
188 | --- a/blockdev.c |
189 | +++ b/blockdev.c | |
68a30562 | 190 | @@ -3277,8 +3277,8 @@ static void do_drive_backup(const char *job_id, const char *device, |
ca0fe5f5 WB |
191 | } |
192 | ||
68a30562 | 193 | backup_start(job_id, bs, target_bs, speed, sync, bmap, |
ca0fe5f5 WB |
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); | |
68a30562 | 198 | bdrv_unref(target_bs); |
ca0fe5f5 | 199 | if (local_err != NULL) { |
ca0fe5f5 | 200 | error_propagate(errp, local_err); |
68a30562 WB |
201 | @@ -3371,7 +3371,7 @@ void do_blockdev_backup(const char *job_id, const char *device, |
202 | } | |
203 | } | |
204 | backup_start(job_id, bs, target_bs, speed, sync, NULL, on_source_error, | |
ca0fe5f5 WB |
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) { | |
ca0fe5f5 | 208 | error_propagate(errp, local_err); |
68a30562 | 209 | } |
ca0fe5f5 | 210 | diff --git a/include/block/block_int.h b/include/block/block_int.h |
68a30562 | 211 | index 1e939de..db4650e 100644 |
ca0fe5f5 WB |
212 | --- a/include/block/block_int.h |
213 | +++ b/include/block/block_int.h | |
68a30562 | 214 | @@ -59,6 +59,9 @@ |
ca0fe5f5 WB |
215 | |
216 | #define BLOCK_PROBE_BUF_SIZE 512 | |
217 | ||
218 | +typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs, | |
219 | + int64_t sector_num, int n_sectors, unsigned char *buf); | |
220 | + | |
221 | enum BdrvTrackedRequestType { | |
222 | BDRV_TRACKED_READ, | |
223 | BDRV_TRACKED_WRITE, | |
68a30562 WB |
224 | @@ -767,7 +770,9 @@ void backup_start(const char *job_id, BlockDriverState *bs, |
225 | MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap, | |
ca0fe5f5 WB |
226 | BlockdevOnError on_source_error, |
227 | BlockdevOnError on_target_error, | |
228 | + BackupDumpFunc *dump_cb, | |
229 | BlockCompletionFunc *cb, void *opaque, | |
230 | + int pause_count, | |
231 | BlockJobTxn *txn, Error **errp); | |
232 | ||
b07d35a5 | 233 | void hmp_drive_add_node(Monitor *mon, const char *optstr); |
ca0fe5f5 WB |
234 | -- |
235 | 2.1.4 | |
236 |