]>
Commit | Line | Data |
---|---|---|
83faa3fe | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
059a9447 | 2 | From: John Snow <jsnow@redhat.com> |
83faa3fe TL |
3 | Date: Mon, 6 Apr 2020 12:17:03 +0200 |
4 | Subject: [PATCH] drive-mirror: add support for sync=bitmap mode=never | |
059a9447 FG |
5 | MIME-Version: 1.0 |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | This patch adds support for the "BITMAP" sync mode to drive-mirror and | |
10 | blockdev-mirror. It adds support only for the BitmapSyncMode "never," | |
11 | because it's the simplest mode. | |
12 | ||
13 | This mode simply uses a user-provided bitmap as an initial copy | |
14 | manifest, and then does not clear any bits in the bitmap at the | |
15 | conclusion of the operation. | |
16 | ||
17 | Any new writes dirtied during the operation are copied out, in contrast | |
18 | to backup. Note that whether these writes are reflected in the bitmap | |
19 | at the conclusion of the operation depends on whether that bitmap is | |
20 | actually recording! | |
21 | ||
22 | This patch was originally based on one by Ma Haocong, but it has since | |
23 | been modified pretty heavily. | |
24 | ||
25 | Suggested-by: Ma Haocong <mahaocong@didichuxing.com> | |
26 | Signed-off-by: Ma Haocong <mahaocong@didichuxing.com> | |
27 | Signed-off-by: John Snow <jsnow@redhat.com> | |
28 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
29 | --- | |
059a9447 FG |
30 | block/mirror.c | 98 ++++++++++++++++++++++++++++++------- |
31 | blockdev.c | 39 +++++++++++++-- | |
83faa3fe | 32 | include/block/block_int.h | 4 +- |
059a9447 | 33 | qapi/block-core.json | 29 +++++++++-- |
83faa3fe | 34 | tests/test-block-iothread.c | 4 +- |
059a9447 FG |
35 | 5 files changed, 145 insertions(+), 29 deletions(-) |
36 | ||
059a9447 | 37 | diff --git a/block/mirror.c b/block/mirror.c |
817b7667 | 38 | index 8e1ad6eceb..97843992c2 100644 |
059a9447 FG |
39 | --- a/block/mirror.c |
40 | +++ b/block/mirror.c | |
817b7667 | 41 | @@ -50,7 +50,7 @@ typedef struct MirrorBlockJob { |
059a9447 FG |
42 | BlockDriverState *to_replace; |
43 | /* Used to block operations on the drive-mirror-replace target */ | |
44 | Error *replace_blocker; | |
45 | - bool is_none_mode; | |
46 | + MirrorSyncMode sync_mode; | |
47 | BlockMirrorBackingMode backing_mode; | |
48 | /* Whether the target image requires explicit zero-initialization */ | |
49 | bool zero_target; | |
817b7667 | 50 | @@ -65,6 +65,8 @@ typedef struct MirrorBlockJob { |
059a9447 FG |
51 | size_t buf_size; |
52 | int64_t bdev_length; | |
53 | unsigned long *cow_bitmap; | |
54 | + BdrvDirtyBitmap *sync_bitmap; | |
55 | + BitmapSyncMode bitmap_mode; | |
56 | BdrvDirtyBitmap *dirty_bitmap; | |
57 | BdrvDirtyBitmapIter *dbi; | |
58 | uint8_t *buf; | |
817b7667 | 59 | @@ -677,7 +679,8 @@ static int mirror_exit_common(Job *job) |
059a9447 FG |
60 | bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing, |
61 | &error_abort); | |
62 | if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) { | |
63 | - BlockDriverState *backing = s->is_none_mode ? src : s->base; | |
64 | + BlockDriverState *backing; | |
65 | + backing = s->sync_mode == MIRROR_SYNC_MODE_NONE ? src : s->base; | |
817b7667 SR |
66 | BlockDriverState *unfiltered_target = bdrv_skip_filters(target_bs); |
67 | ||
68 | if (bdrv_cow_bs(unfiltered_target) != backing) { | |
69 | @@ -774,6 +777,16 @@ static void mirror_abort(Job *job) | |
059a9447 FG |
70 | assert(ret == 0); |
71 | } | |
72 | ||
73 | +/* Always called after commit/abort. */ | |
74 | +static void mirror_clean(Job *job) | |
75 | +{ | |
76 | + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); | |
77 | + | |
78 | + if (s->sync_bitmap) { | |
79 | + bdrv_dirty_bitmap_set_busy(s->sync_bitmap, false); | |
80 | + } | |
81 | +} | |
82 | + | |
83 | static void coroutine_fn mirror_throttle(MirrorBlockJob *s) | |
84 | { | |
85 | int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); | |
817b7667 | 86 | @@ -955,7 +968,8 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) |
059a9447 FG |
87 | mirror_free_init(s); |
88 | ||
89 | s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); | |
90 | - if (!s->is_none_mode) { | |
91 | + if ((s->sync_mode == MIRROR_SYNC_MODE_TOP) || | |
92 | + (s->sync_mode == MIRROR_SYNC_MODE_FULL)) { | |
93 | ret = mirror_dirty_init(s); | |
94 | if (ret < 0 || job_is_cancelled(&s->common.job)) { | |
95 | goto immediate_exit; | |
817b7667 | 96 | @@ -1188,6 +1202,7 @@ static const BlockJobDriver mirror_job_driver = { |
059a9447 FG |
97 | .run = mirror_run, |
98 | .prepare = mirror_prepare, | |
99 | .abort = mirror_abort, | |
100 | + .clean = mirror_clean, | |
101 | .pause = mirror_pause, | |
102 | .complete = mirror_complete, | |
103 | }, | |
817b7667 | 104 | @@ -1203,6 +1218,7 @@ static const BlockJobDriver commit_active_job_driver = { |
059a9447 FG |
105 | .run = mirror_run, |
106 | .prepare = mirror_prepare, | |
107 | .abort = mirror_abort, | |
108 | + .clean = mirror_clean, | |
109 | .pause = mirror_pause, | |
110 | .complete = mirror_complete, | |
111 | }, | |
817b7667 | 112 | @@ -1550,7 +1566,10 @@ static BlockJob *mirror_start_job( |
059a9447 FG |
113 | BlockCompletionFunc *cb, |
114 | void *opaque, | |
115 | const BlockJobDriver *driver, | |
116 | - bool is_none_mode, BlockDriverState *base, | |
117 | + MirrorSyncMode sync_mode, | |
118 | + BdrvDirtyBitmap *bitmap, | |
119 | + BitmapSyncMode bitmap_mode, | |
120 | + BlockDriverState *base, | |
121 | bool auto_complete, const char *filter_node_name, | |
122 | bool is_mirror, MirrorCopyMode copy_mode, | |
123 | Error **errp) | |
817b7667 | 124 | @@ -1563,10 +1582,39 @@ static BlockJob *mirror_start_job( |
059a9447 FG |
125 | Error *local_err = NULL; |
126 | int ret; | |
127 | ||
128 | - if (granularity == 0) { | |
129 | - granularity = bdrv_get_default_bitmap_granularity(target); | |
130 | + if (sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { | |
131 | + error_setg(errp, "Sync mode '%s' not supported", | |
132 | + MirrorSyncMode_str(sync_mode)); | |
133 | + return NULL; | |
134 | + } else if (sync_mode == MIRROR_SYNC_MODE_BITMAP) { | |
135 | + if (!bitmap) { | |
136 | + error_setg(errp, "Must provide a valid bitmap name for '%s'" | |
137 | + " sync mode", | |
138 | + MirrorSyncMode_str(sync_mode)); | |
139 | + return NULL; | |
140 | + } else if (bitmap_mode != BITMAP_SYNC_MODE_NEVER) { | |
141 | + error_setg(errp, | |
142 | + "Bitmap Sync Mode '%s' is not supported by Mirror", | |
143 | + BitmapSyncMode_str(bitmap_mode)); | |
144 | + } | |
145 | + } else if (bitmap) { | |
146 | + error_setg(errp, | |
147 | + "sync mode '%s' is not compatible with bitmaps", | |
148 | + MirrorSyncMode_str(sync_mode)); | |
149 | + return NULL; | |
150 | } | |
151 | ||
152 | + if (bitmap) { | |
153 | + if (granularity) { | |
154 | + error_setg(errp, "granularity (%d)" | |
155 | + "cannot be specified when a bitmap is provided", | |
156 | + granularity); | |
157 | + return NULL; | |
158 | + } | |
159 | + granularity = bdrv_dirty_bitmap_granularity(bitmap); | |
160 | + } else if (granularity == 0) { | |
161 | + granularity = bdrv_get_default_bitmap_granularity(target); | |
162 | + } | |
163 | assert(is_power_of_2(granularity)); | |
164 | ||
165 | if (buf_size < 0) { | |
817b7667 | 166 | @@ -1705,7 +1753,9 @@ static BlockJob *mirror_start_job( |
059a9447 FG |
167 | s->replaces = g_strdup(replaces); |
168 | s->on_source_error = on_source_error; | |
169 | s->on_target_error = on_target_error; | |
170 | - s->is_none_mode = is_none_mode; | |
171 | + s->sync_mode = sync_mode; | |
172 | + s->sync_bitmap = bitmap; | |
173 | + s->bitmap_mode = bitmap_mode; | |
174 | s->backing_mode = backing_mode; | |
175 | s->zero_target = zero_target; | |
176 | s->copy_mode = copy_mode; | |
817b7667 | 177 | @@ -1726,6 +1776,18 @@ static BlockJob *mirror_start_job( |
059a9447 FG |
178 | bdrv_disable_dirty_bitmap(s->dirty_bitmap); |
179 | } | |
180 | ||
181 | + if (s->sync_bitmap) { | |
182 | + bdrv_dirty_bitmap_set_busy(s->sync_bitmap, true); | |
183 | + } | |
184 | + | |
185 | + if (s->sync_mode == MIRROR_SYNC_MODE_BITMAP) { | |
186 | + bdrv_merge_dirty_bitmap(s->dirty_bitmap, s->sync_bitmap, | |
187 | + NULL, &local_err); | |
188 | + if (local_err) { | |
189 | + goto fail; | |
190 | + } | |
191 | + } | |
192 | + | |
193 | ret = block_job_add_bdrv(&s->common, "source", bs, 0, | |
194 | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE | | |
195 | BLK_PERM_CONSISTENT_READ, | |
817b7667 | 196 | @@ -1803,6 +1865,9 @@ fail: |
059a9447 FG |
197 | if (s->dirty_bitmap) { |
198 | bdrv_release_dirty_bitmap(s->dirty_bitmap); | |
199 | } | |
200 | + if (s->sync_bitmap) { | |
201 | + bdrv_dirty_bitmap_set_busy(s->sync_bitmap, false); | |
202 | + } | |
203 | job_early_fail(&s->common.job); | |
204 | } | |
205 | ||
817b7667 | 206 | @@ -1820,29 +1885,23 @@ void mirror_start(const char *job_id, BlockDriverState *bs, |
059a9447 FG |
207 | BlockDriverState *target, const char *replaces, |
208 | int creation_flags, int64_t speed, | |
209 | uint32_t granularity, int64_t buf_size, | |
210 | - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, | |
211 | + MirrorSyncMode mode, BdrvDirtyBitmap *bitmap, | |
212 | + BitmapSyncMode bitmap_mode, | |
213 | + BlockMirrorBackingMode backing_mode, | |
214 | bool zero_target, | |
215 | BlockdevOnError on_source_error, | |
216 | BlockdevOnError on_target_error, | |
217 | bool unmap, const char *filter_node_name, | |
218 | MirrorCopyMode copy_mode, Error **errp) | |
219 | { | |
220 | - bool is_none_mode; | |
221 | BlockDriverState *base; | |
222 | ||
223 | - if ((mode == MIRROR_SYNC_MODE_INCREMENTAL) || | |
224 | - (mode == MIRROR_SYNC_MODE_BITMAP)) { | |
225 | - error_setg(errp, "Sync mode '%s' not supported", | |
226 | - MirrorSyncMode_str(mode)); | |
227 | - return; | |
228 | - } | |
229 | - is_none_mode = mode == MIRROR_SYNC_MODE_NONE; | |
817b7667 | 230 | base = mode == MIRROR_SYNC_MODE_TOP ? bdrv_backing_chain_next(bs) : NULL; |
059a9447 FG |
231 | mirror_start_job(job_id, bs, creation_flags, target, replaces, |
232 | speed, granularity, buf_size, backing_mode, zero_target, | |
233 | on_source_error, on_target_error, unmap, NULL, NULL, | |
234 | - &mirror_job_driver, is_none_mode, base, false, | |
235 | - filter_node_name, true, copy_mode, errp); | |
236 | + &mirror_job_driver, mode, bitmap, bitmap_mode, base, | |
237 | + false, filter_node_name, true, copy_mode, errp); | |
238 | } | |
239 | ||
240 | BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, | |
817b7667 | 241 | @@ -1868,7 +1927,8 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, |
059a9447 FG |
242 | job_id, bs, creation_flags, base, NULL, speed, 0, 0, |
243 | MIRROR_LEAVE_BACKING_CHAIN, false, | |
244 | on_error, on_error, true, cb, opaque, | |
245 | - &commit_active_job_driver, false, base, auto_complete, | |
246 | + &commit_active_job_driver, MIRROR_SYNC_MODE_FULL, | |
247 | + NULL, 0, base, auto_complete, | |
248 | filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND, | |
249 | &local_err); | |
250 | if (local_err) { | |
251 | diff --git a/blockdev.c b/blockdev.c | |
2413972b | 252 | index fe6fb5dc1d..394920613d 100644 |
059a9447 FG |
253 | --- a/blockdev.c |
254 | +++ b/blockdev.c | |
2413972b | 255 | @@ -2930,6 +2930,10 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, |
059a9447 FG |
256 | BlockDriverState *target, |
257 | bool has_replaces, const char *replaces, | |
258 | enum MirrorSyncMode sync, | |
259 | + bool has_bitmap, | |
260 | + const char *bitmap_name, | |
261 | + bool has_bitmap_mode, | |
262 | + BitmapSyncMode bitmap_mode, | |
263 | BlockMirrorBackingMode backing_mode, | |
264 | bool zero_target, | |
265 | bool has_speed, int64_t speed, | |
2413972b | 266 | @@ -2949,6 +2953,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, |
059a9447 | 267 | { |
817b7667 | 268 | BlockDriverState *unfiltered_bs; |
059a9447 FG |
269 | int job_flags = JOB_DEFAULT; |
270 | + BdrvDirtyBitmap *bitmap = NULL; | |
271 | ||
272 | if (!has_speed) { | |
273 | speed = 0; | |
2413972b | 274 | @@ -3003,6 +3008,29 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, |
059a9447 FG |
275 | sync = MIRROR_SYNC_MODE_FULL; |
276 | } | |
277 | ||
278 | + if (has_bitmap) { | |
279 | + if (granularity) { | |
280 | + error_setg(errp, "Granularity and bitmap cannot both be set"); | |
281 | + return; | |
282 | + } | |
283 | + | |
284 | + if (!has_bitmap_mode) { | |
285 | + error_setg(errp, "bitmap-mode must be specified if" | |
286 | + " a bitmap is provided"); | |
287 | + return; | |
288 | + } | |
289 | + | |
290 | + bitmap = bdrv_find_dirty_bitmap(bs, bitmap_name); | |
291 | + if (!bitmap) { | |
292 | + error_setg(errp, "Dirty bitmap '%s' not found", bitmap_name); | |
293 | + return; | |
294 | + } | |
295 | + | |
296 | + if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { | |
297 | + return; | |
298 | + } | |
299 | + } | |
300 | + | |
817b7667 SR |
301 | if (!has_replaces) { |
302 | /* We want to mirror from @bs, but keep implicit filters on top */ | |
303 | unfiltered_bs = bdrv_skip_implicit_filters(bs); | |
2413972b | 304 | @@ -3049,8 +3077,8 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, |
059a9447 FG |
305 | * and will allow to check whether the node still exist at mirror completion |
306 | */ | |
307 | mirror_start(job_id, bs, target, | |
308 | - has_replaces ? replaces : NULL, job_flags, | |
309 | - speed, granularity, buf_size, sync, backing_mode, zero_target, | |
310 | + has_replaces ? replaces : NULL, job_flags, speed, granularity, | |
311 | + buf_size, sync, bitmap, bitmap_mode, backing_mode, zero_target, | |
312 | on_source_error, on_target_error, unmap, filter_node_name, | |
313 | copy_mode, errp); | |
314 | } | |
2413972b | 315 | @@ -3195,6 +3223,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) |
059a9447 FG |
316 | |
317 | blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs, | |
318 | arg->has_replaces, arg->replaces, arg->sync, | |
319 | + arg->has_bitmap, arg->bitmap, | |
320 | + arg->has_bitmap_mode, arg->bitmap_mode, | |
321 | backing_mode, zero_target, | |
322 | arg->has_speed, arg->speed, | |
323 | arg->has_granularity, arg->granularity, | |
2413972b | 324 | @@ -3216,6 +3246,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, |
059a9447 FG |
325 | const char *device, const char *target, |
326 | bool has_replaces, const char *replaces, | |
327 | MirrorSyncMode sync, | |
328 | + bool has_bitmap, const char *bitmap, | |
329 | + bool has_bitmap_mode, BitmapSyncMode bitmap_mode, | |
330 | bool has_speed, int64_t speed, | |
331 | bool has_granularity, uint32_t granularity, | |
332 | bool has_buf_size, int64_t buf_size, | |
2413972b | 333 | @@ -3265,7 +3297,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, |
059a9447 FG |
334 | } |
335 | ||
336 | blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, | |
337 | - has_replaces, replaces, sync, backing_mode, | |
338 | + has_replaces, replaces, sync, has_bitmap, | |
339 | + bitmap, has_bitmap_mode, bitmap_mode, backing_mode, | |
340 | zero_target, has_speed, speed, | |
341 | has_granularity, granularity, | |
342 | has_buf_size, buf_size, | |
83faa3fe | 343 | diff --git a/include/block/block_int.h b/include/block/block_int.h |
2413972b | 344 | index 95d9333be1..6f8eda629a 100644 |
83faa3fe TL |
345 | --- a/include/block/block_int.h |
346 | +++ b/include/block/block_int.h | |
2413972b | 347 | @@ -1230,7 +1230,9 @@ void mirror_start(const char *job_id, BlockDriverState *bs, |
83faa3fe TL |
348 | BlockDriverState *target, const char *replaces, |
349 | int creation_flags, int64_t speed, | |
350 | uint32_t granularity, int64_t buf_size, | |
351 | - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, | |
352 | + MirrorSyncMode mode, BdrvDirtyBitmap *bitmap, | |
353 | + BitmapSyncMode bitmap_mode, | |
354 | + BlockMirrorBackingMode backing_mode, | |
355 | bool zero_target, | |
356 | BlockdevOnError on_source_error, | |
357 | BlockdevOnError on_target_error, | |
059a9447 | 358 | diff --git a/qapi/block-core.json b/qapi/block-core.json |
2413972b | 359 | index 04ad80bc1e..9db3120716 100644 |
059a9447 FG |
360 | --- a/qapi/block-core.json |
361 | +++ b/qapi/block-core.json | |
2413972b | 362 | @@ -1971,10 +1971,19 @@ |
059a9447 FG |
363 | # (all the disk, only the sectors allocated in the topmost image, or |
364 | # only new I/O). | |
365 | # | |
366 | +# @bitmap: The name of a bitmap to use for sync=bitmap mode. This argument must | |
367 | +# be present for bitmap mode and absent otherwise. The bitmap's | |
368 | +# granularity is used instead of @granularity (since 4.1). | |
369 | +# | |
370 | +# @bitmap-mode: Specifies the type of data the bitmap should contain after | |
371 | +# the operation concludes. Must be present if sync is "bitmap". | |
372 | +# Must NOT be present otherwise. (Since 4.1) | |
373 | +# | |
374 | # @granularity: granularity of the dirty bitmap, default is 64K | |
375 | # if the image format doesn't have clusters, 4K if the clusters | |
376 | # are smaller than that, else the cluster size. Must be a | |
377 | -# power of 2 between 512 and 64M (since 1.4). | |
378 | +# power of 2 between 512 and 64M. Must not be specified if | |
379 | +# @bitmap is present (since 1.4). | |
380 | # | |
381 | # @buf-size: maximum amount of data in flight from source to | |
382 | # target (since 1.4). | |
2413972b | 383 | @@ -2012,7 +2021,9 @@ |
059a9447 FG |
384 | { 'struct': 'DriveMirror', |
385 | 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', | |
386 | '*format': 'str', '*node-name': 'str', '*replaces': 'str', | |
387 | - 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', | |
388 | + 'sync': 'MirrorSyncMode', '*bitmap': 'str', | |
389 | + '*bitmap-mode': 'BitmapSyncMode', | |
390 | + '*mode': 'NewImageMode', | |
391 | '*speed': 'int', '*granularity': 'uint32', | |
392 | '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', | |
393 | '*on-target-error': 'BlockdevOnError', | |
2413972b | 394 | @@ -2280,10 +2291,19 @@ |
059a9447 FG |
395 | # (all the disk, only the sectors allocated in the topmost image, or |
396 | # only new I/O). | |
397 | # | |
398 | +# @bitmap: The name of a bitmap to use for sync=bitmap mode. This argument must | |
399 | +# be present for bitmap mode and absent otherwise. The bitmap's | |
400 | +# granularity is used instead of @granularity (since 4.1). | |
401 | +# | |
402 | +# @bitmap-mode: Specifies the type of data the bitmap should contain after | |
403 | +# the operation concludes. Must be present if sync is "bitmap". | |
404 | +# Must NOT be present otherwise. (Since 4.1) | |
405 | +# | |
406 | # @granularity: granularity of the dirty bitmap, default is 64K | |
407 | # if the image format doesn't have clusters, 4K if the clusters | |
408 | # are smaller than that, else the cluster size. Must be a | |
409 | -# power of 2 between 512 and 64M | |
410 | +# power of 2 between 512 and 64M . Must not be specified if | |
411 | +# @bitmap is present. | |
412 | # | |
413 | # @buf-size: maximum amount of data in flight from source to | |
414 | # target | |
2413972b | 415 | @@ -2332,7 +2352,8 @@ |
059a9447 FG |
416 | { 'command': 'blockdev-mirror', |
417 | 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', | |
418 | '*replaces': 'str', | |
419 | - 'sync': 'MirrorSyncMode', | |
420 | + 'sync': 'MirrorSyncMode', '*bitmap': 'str', | |
421 | + '*bitmap-mode': 'BitmapSyncMode', | |
422 | '*speed': 'int', '*granularity': 'uint32', | |
423 | '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', | |
424 | '*on-target-error': 'BlockdevOnError', | |
83faa3fe | 425 | diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c |
60ae3775 | 426 | index 3f866a35c6..500ede71c8 100644 |
83faa3fe TL |
427 | --- a/tests/test-block-iothread.c |
428 | +++ b/tests/test-block-iothread.c | |
60ae3775 | 429 | @@ -623,8 +623,8 @@ static void test_propagate_mirror(void) |
83faa3fe TL |
430 | |
431 | /* Start a mirror job */ | |
432 | mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0, | |
433 | - MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false, | |
434 | - BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT, | |
435 | + MIRROR_SYNC_MODE_NONE, NULL, 0, MIRROR_OPEN_BACKING_CHAIN, | |
436 | + false, BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT, | |
437 | false, "filter_node", MIRROR_COPY_MODE_BACKGROUND, | |
438 | &error_abort); | |
439 | job = job_get("job0"); |