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