]>
Commit | Line | Data |
---|---|---|
ca0fe5f5 WB |
1 | From 2ec6f9ec8443f3389c74e8e21353d01e516c4f46 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 | |
b07d35a5 | 4 | Subject: [PATCH 15/54] 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 | --- | |
b07d35a5 TL |
10 | block/backup.c | 90 ++++++++++++++++++++++++++++++----------------- |
11 | blockdev.c | 6 ++-- | |
12 | include/block/block_int.h | 5 +++ | |
13 | 3 files changed, 65 insertions(+), 36 deletions(-) | |
ca0fe5f5 WB |
14 | |
15 | diff --git a/block/backup.c b/block/backup.c | |
16 | index 705bb77..7ac6b29 100644 | |
17 | --- a/block/backup.c | |
18 | +++ b/block/backup.c | |
19 | @@ -43,6 +43,7 @@ typedef struct BackupBlockJob { | |
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; | |
27 | @@ -147,14 +148,21 @@ static int coroutine_fn backup_do_cow(BlockDriverState *bs, | |
28 | goto out; | |
29 | } | |
30 | ||
b07d35a5 | 31 | + int64_t start_sec = start * sectors_per_cluster; |
ca0fe5f5 WB |
32 | if (buffer_is_zero(iov.iov_base, iov.iov_len)) { |
33 | - ret = bdrv_co_write_zeroes(job->target, | |
b07d35a5 | 34 | - start * sectors_per_cluster, |
ca0fe5f5 WB |
35 | - n, BDRV_REQ_MAY_UNMAP); |
36 | + if (job->dump_cb) { | |
37 | + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, NULL); | |
38 | + } | |
39 | + if (job->target) { | |
40 | + ret = bdrv_co_write_zeroes(job->target, start_sec, n, BDRV_REQ_MAY_UNMAP); | |
41 | + } | |
42 | } else { | |
43 | - ret = bdrv_co_writev(job->target, | |
b07d35a5 | 44 | - start * sectors_per_cluster, n, |
ca0fe5f5 WB |
45 | - &bounce_qiov); |
46 | + if (job->dump_cb) { | |
47 | + ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, bounce_buffer); | |
48 | + } | |
49 | + if (job->target) { | |
50 | + ret = bdrv_co_writev(job->target, start_sec, n, &bounce_qiov); | |
51 | + } | |
52 | } | |
53 | if (ret < 0) { | |
54 | trace_backup_do_cow_write_fail(job, start, ret); | |
55 | @@ -216,7 +224,7 @@ static void backup_iostatus_reset(BlockJob *job) | |
56 | { | |
57 | BackupBlockJob *s = container_of(job, BackupBlockJob, common); | |
58 | ||
59 | - if (s->target->blk) { | |
60 | + if (s->target && s->target->blk) { | |
61 | blk_iostatus_reset(s->target->blk); | |
62 | } | |
63 | } | |
64 | @@ -268,9 +276,11 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job, | |
65 | if (read) { | |
66 | return block_job_error_action(&job->common, job->common.bs, | |
67 | job->on_source_error, true, error); | |
68 | - } else { | |
69 | + } else if (job->target) { | |
70 | return block_job_error_action(&job->common, job->target, | |
71 | job->on_target_error, false, error); | |
72 | + } else { | |
73 | + return BLOCK_ERROR_ACTION_REPORT; | |
74 | } | |
75 | } | |
76 | ||
b07d35a5 | 77 | @@ -404,9 +414,12 @@ static void coroutine_fn backup_run(void *opaque) |
ca0fe5f5 | 78 | |
b07d35a5 | 79 | job->done_bitmap = bitmap_new(end); |
ca0fe5f5 | 80 | |
ca0fe5f5 WB |
81 | - if (target->blk) { |
82 | - blk_set_on_error(target->blk, on_target_error, on_target_error); | |
83 | - blk_iostatus_enable(target->blk); | |
84 | + if (target) { | |
85 | + bdrv_set_enable_write_cache(target, true); | |
86 | + if (target->blk) { | |
87 | + blk_set_on_error(target->blk, on_target_error, on_target_error); | |
88 | + blk_iostatus_enable(target->blk); | |
89 | + } | |
90 | } | |
91 | ||
92 | bdrv_add_before_write_notifier(bs, &before_write); | |
b07d35a5 | 93 | @@ -484,10 +497,12 @@ static void coroutine_fn backup_run(void *opaque) |
ca0fe5f5 | 94 | qemu_co_rwlock_unlock(&job->flush_rwlock); |
b07d35a5 | 95 | g_free(job->done_bitmap); |
ca0fe5f5 WB |
96 | |
97 | - if (target->blk) { | |
98 | - blk_iostatus_disable(target->blk); | |
99 | + if (target) { | |
100 | + if (target->blk) { | |
101 | + blk_iostatus_disable(target->blk); | |
102 | + } | |
103 | + bdrv_op_unblock_all(target, job->common.blocker); | |
104 | } | |
105 | - bdrv_op_unblock_all(target, job->common.blocker); | |
106 | ||
107 | data = g_malloc(sizeof(*data)); | |
108 | data->ret = ret; | |
b07d35a5 | 109 | @@ -499,7 +514,9 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, |
ca0fe5f5 WB |
110 | BdrvDirtyBitmap *sync_bitmap, |
111 | BlockdevOnError on_source_error, | |
112 | BlockdevOnError on_target_error, | |
113 | + BackupDumpFunc *dump_cb, | |
114 | BlockCompletionFunc *cb, void *opaque, | |
115 | + int pause_count, | |
116 | BlockJobTxn *txn, Error **errp) | |
117 | { | |
118 | int64_t len; | |
b07d35a5 TL |
119 | @@ -507,7 +524,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, |
120 | int ret; | |
ca0fe5f5 WB |
121 | |
122 | assert(bs); | |
123 | - assert(target); | |
124 | + assert(target || dump_cb); | |
125 | assert(cb); | |
126 | ||
127 | if (bs == target) { | |
128 | @@ -519,7 +535,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, | |
129 | return; | |
130 | } | |
131 | ||
132 | - if (!bdrv_is_inserted(target)) { | |
133 | + if (target && !bdrv_is_inserted(target)) { | |
134 | error_setg(errp, "Device is not inserted: %s", | |
135 | bdrv_get_device_name(target)); | |
136 | return; | |
137 | @@ -529,7 +545,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, | |
138 | return; | |
139 | } | |
140 | ||
141 | - if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) { | |
142 | + if (target && bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) { | |
143 | return; | |
144 | } | |
145 | ||
b07d35a5 | 146 | @@ -574,6 +591,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, |
ca0fe5f5 WB |
147 | goto error; |
148 | } | |
149 | ||
ca0fe5f5 WB |
150 | + job->dump_cb = dump_cb; |
151 | job->on_source_error = on_source_error; | |
152 | job->on_target_error = on_target_error; | |
153 | job->target = target; | |
b07d35a5 | 154 | @@ -581,25 +599,31 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, |
ca0fe5f5 WB |
155 | job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ? |
156 | sync_bitmap : NULL; | |
b07d35a5 TL |
157 | |
158 | - /* If there is no backing file on the target, we cannot rely on COW if our | |
159 | - * backup cluster size is smaller than the target cluster size. Even for | |
160 | - * targets with a backing file, try to avoid COW if possible. */ | |
161 | - ret = bdrv_get_info(job->target, &bdi); | |
162 | - if (ret < 0 && !target->backing) { | |
163 | - error_setg_errno(errp, -ret, | |
164 | - "Couldn't determine the cluster size of the target image, " | |
165 | - "which has no backing file"); | |
166 | - error_append_hint(errp, | |
167 | - "Aborting, since this may create an unusable destination image\n"); | |
168 | - goto error; | |
169 | - } else if (ret < 0 && target->backing) { | |
170 | - /* Not fatal; just trudge on ahead. */ | |
171 | - job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; | |
172 | + if (target) { | |
173 | + /* If there is no backing file on the target, we cannot rely on COW if our | |
174 | + * backup cluster size is smaller than the target cluster size. Even for | |
175 | + * targets with a backing file, try to avoid COW if possible. */ | |
176 | + ret = bdrv_get_info(job->target, &bdi); | |
177 | + if (ret < 0 && !target->backing) { | |
178 | + error_setg_errno(errp, -ret, | |
179 | + "Couldn't determine the cluster size of the target image, " | |
180 | + "which has no backing file"); | |
181 | + error_append_hint(errp, | |
182 | + "Aborting, since this may create an unusable destination image\n"); | |
183 | + goto error; | |
184 | + } else if (ret < 0 && target->backing) { | |
185 | + /* Not fatal; just trudge on ahead. */ | |
186 | + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; | |
187 | + } else { | |
188 | + job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size); | |
189 | + } | |
190 | + | |
191 | + bdrv_op_block_all(target, job->common.blocker); | |
192 | } else { | |
193 | - job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size); | |
194 | + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; | |
195 | } | |
196 | ||
197 | - bdrv_op_block_all(target, job->common.blocker); | |
ca0fe5f5 WB |
198 | + job->common.pause_count = pause_count; |
199 | job->common.len = len; | |
200 | job->common.co = qemu_coroutine_create(backup_run); | |
201 | block_job_txn_add_job(txn, &job->common); | |
202 | diff --git a/blockdev.c b/blockdev.c | |
203 | index 80932e8..1796eaf 100644 | |
204 | --- a/blockdev.c | |
205 | +++ b/blockdev.c | |
206 | @@ -3178,8 +3178,8 @@ static void do_drive_backup(const char *device, const char *target, | |
207 | } | |
208 | ||
209 | backup_start(bs, target_bs, speed, sync, bmap, | |
210 | - on_source_error, on_target_error, | |
211 | - block_job_cb, bs, txn, &local_err); | |
212 | + on_source_error, on_target_error, NULL, | |
213 | + block_job_cb, bs, 0, txn, &local_err); | |
214 | if (local_err != NULL) { | |
215 | bdrv_unref(target_bs); | |
216 | error_propagate(errp, local_err); | |
217 | @@ -3268,7 +3268,7 @@ void do_blockdev_backup(const char *device, const char *target, | |
218 | bdrv_ref(target_bs); | |
219 | bdrv_set_aio_context(target_bs, aio_context); | |
220 | backup_start(bs, target_bs, speed, sync, NULL, on_source_error, | |
221 | - on_target_error, block_job_cb, bs, txn, &local_err); | |
222 | + on_target_error, NULL, block_job_cb, bs, 0, txn, &local_err); | |
223 | if (local_err != NULL) { | |
224 | bdrv_unref(target_bs); | |
225 | error_propagate(errp, local_err); | |
226 | diff --git a/include/block/block_int.h b/include/block/block_int.h | |
227 | index 4012e36..f4b6ecd 100644 | |
228 | --- a/include/block/block_int.h | |
229 | +++ b/include/block/block_int.h | |
230 | @@ -60,6 +60,9 @@ | |
231 | ||
232 | #define BLOCK_PROBE_BUF_SIZE 512 | |
233 | ||
234 | +typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs, | |
235 | + int64_t sector_num, int n_sectors, unsigned char *buf); | |
236 | + | |
237 | enum BdrvTrackedRequestType { | |
238 | BDRV_TRACKED_READ, | |
239 | BDRV_TRACKED_WRITE, | |
240 | @@ -679,7 +682,9 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, | |
241 | BdrvDirtyBitmap *sync_bitmap, | |
242 | BlockdevOnError on_source_error, | |
243 | BlockdevOnError on_target_error, | |
244 | + BackupDumpFunc *dump_cb, | |
245 | BlockCompletionFunc *cb, void *opaque, | |
246 | + int pause_count, | |
247 | BlockJobTxn *txn, Error **errp); | |
248 | ||
b07d35a5 | 249 | void hmp_drive_add_node(Monitor *mon, const char *optstr); |
ca0fe5f5 WB |
250 | -- |
251 | 2.1.4 | |
252 |