2020-04-07 17:53:19 +03:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
2020-03-17 10:55:24 +03:00
|
|
|
From: John Snow <jsnow@redhat.com>
|
2020-04-07 17:53:19 +03:00
|
|
|
Date: Mon, 6 Apr 2020 12:17:03 +0200
|
|
|
|
Subject: [PATCH] drive-mirror: add support for sync=bitmap mode=never
|
2020-03-17 10:55:24 +03:00
|
|
|
MIME-Version: 1.0
|
|
|
|
Content-Type: text/plain; charset=UTF-8
|
|
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
|
|
|
|
This patch adds support for the "BITMAP" sync mode to drive-mirror and
|
|
|
|
blockdev-mirror. It adds support only for the BitmapSyncMode "never,"
|
|
|
|
because it's the simplest mode.
|
|
|
|
|
|
|
|
This mode simply uses a user-provided bitmap as an initial copy
|
|
|
|
manifest, and then does not clear any bits in the bitmap at the
|
|
|
|
conclusion of the operation.
|
|
|
|
|
|
|
|
Any new writes dirtied during the operation are copied out, in contrast
|
|
|
|
to backup. Note that whether these writes are reflected in the bitmap
|
|
|
|
at the conclusion of the operation depends on whether that bitmap is
|
|
|
|
actually recording!
|
|
|
|
|
|
|
|
This patch was originally based on one by Ma Haocong, but it has since
|
|
|
|
been modified pretty heavily.
|
|
|
|
|
|
|
|
Suggested-by: Ma Haocong <mahaocong@didichuxing.com>
|
|
|
|
Signed-off-by: Ma Haocong <mahaocong@didichuxing.com>
|
|
|
|
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
|
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
2022-01-13 12:34:33 +03:00
|
|
|
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
2020-03-17 10:55:24 +03:00
|
|
|
---
|
2022-06-27 14:05:40 +03:00
|
|
|
block/mirror.c | 98 +++++++++++++++++++++-----
|
|
|
|
blockdev.c | 39 +++++++++-
|
|
|
|
include/block/block_int-global-state.h | 4 +-
|
|
|
|
qapi/block-core.json | 29 ++++++--
|
|
|
|
tests/unit/test-block-iothread.c | 4 +-
|
2020-03-17 10:55:24 +03:00
|
|
|
5 files changed, 145 insertions(+), 29 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/block/mirror.c b/block/mirror.c
|
2022-12-14 17:16:32 +03:00
|
|
|
index 251adc5ae0..8ead5f77a0 100644
|
2020-03-17 10:55:24 +03:00
|
|
|
--- a/block/mirror.c
|
|
|
|
+++ b/block/mirror.c
|
2022-06-27 14:05:40 +03:00
|
|
|
@@ -51,7 +51,7 @@ typedef struct MirrorBlockJob {
|
2020-03-17 10:55:24 +03:00
|
|
|
BlockDriverState *to_replace;
|
|
|
|
/* Used to block operations on the drive-mirror-replace target */
|
|
|
|
Error *replace_blocker;
|
|
|
|
- bool is_none_mode;
|
|
|
|
+ MirrorSyncMode sync_mode;
|
|
|
|
BlockMirrorBackingMode backing_mode;
|
|
|
|
/* Whether the target image requires explicit zero-initialization */
|
|
|
|
bool zero_target;
|
2022-06-27 14:05:40 +03:00
|
|
|
@@ -65,6 +65,8 @@ typedef struct MirrorBlockJob {
|
2020-03-17 10:55:24 +03:00
|
|
|
size_t buf_size;
|
|
|
|
int64_t bdev_length;
|
|
|
|
unsigned long *cow_bitmap;
|
|
|
|
+ BdrvDirtyBitmap *sync_bitmap;
|
|
|
|
+ BitmapSyncMode bitmap_mode;
|
|
|
|
BdrvDirtyBitmap *dirty_bitmap;
|
|
|
|
BdrvDirtyBitmapIter *dbi;
|
|
|
|
uint8_t *buf;
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -699,7 +701,8 @@ static int mirror_exit_common(Job *job)
|
2020-03-17 10:55:24 +03:00
|
|
|
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
|
|
|
|
&error_abort);
|
|
|
|
if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {
|
|
|
|
- BlockDriverState *backing = s->is_none_mode ? src : s->base;
|
|
|
|
+ BlockDriverState *backing;
|
|
|
|
+ backing = s->sync_mode == MIRROR_SYNC_MODE_NONE ? src : s->base;
|
2021-02-11 19:11:11 +03:00
|
|
|
BlockDriverState *unfiltered_target = bdrv_skip_filters(target_bs);
|
|
|
|
|
|
|
|
if (bdrv_cow_bs(unfiltered_target) != backing) {
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -797,6 +800,16 @@ static void mirror_abort(Job *job)
|
2020-03-17 10:55:24 +03:00
|
|
|
assert(ret == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
+/* Always called after commit/abort. */
|
|
|
|
+static void mirror_clean(Job *job)
|
|
|
|
+{
|
|
|
|
+ MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
|
|
|
|
+
|
|
|
|
+ if (s->sync_bitmap) {
|
|
|
|
+ bdrv_dirty_bitmap_set_busy(s->sync_bitmap, false);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void coroutine_fn mirror_throttle(MirrorBlockJob *s)
|
|
|
|
{
|
|
|
|
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -977,7 +990,8 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
2020-03-17 10:55:24 +03:00
|
|
|
mirror_free_init(s);
|
|
|
|
|
|
|
|
s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
|
|
|
- if (!s->is_none_mode) {
|
|
|
|
+ if ((s->sync_mode == MIRROR_SYNC_MODE_TOP) ||
|
|
|
|
+ (s->sync_mode == MIRROR_SYNC_MODE_FULL)) {
|
|
|
|
ret = mirror_dirty_init(s);
|
|
|
|
if (ret < 0 || job_is_cancelled(&s->common.job)) {
|
|
|
|
goto immediate_exit;
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1224,6 +1238,7 @@ static const BlockJobDriver mirror_job_driver = {
|
2020-03-17 10:55:24 +03:00
|
|
|
.run = mirror_run,
|
|
|
|
.prepare = mirror_prepare,
|
|
|
|
.abort = mirror_abort,
|
|
|
|
+ .clean = mirror_clean,
|
|
|
|
.pause = mirror_pause,
|
|
|
|
.complete = mirror_complete,
|
2021-05-27 13:43:32 +03:00
|
|
|
.cancel = mirror_cancel,
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1240,6 +1255,7 @@ static const BlockJobDriver commit_active_job_driver = {
|
2020-03-17 10:55:24 +03:00
|
|
|
.run = mirror_run,
|
|
|
|
.prepare = mirror_prepare,
|
|
|
|
.abort = mirror_abort,
|
|
|
|
+ .clean = mirror_clean,
|
|
|
|
.pause = mirror_pause,
|
|
|
|
.complete = mirror_complete,
|
2022-02-11 12:24:33 +03:00
|
|
|
.cancel = commit_active_cancel,
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1627,7 +1643,10 @@ static BlockJob *mirror_start_job(
|
2020-03-17 10:55:24 +03:00
|
|
|
BlockCompletionFunc *cb,
|
|
|
|
void *opaque,
|
|
|
|
const BlockJobDriver *driver,
|
|
|
|
- bool is_none_mode, BlockDriverState *base,
|
|
|
|
+ MirrorSyncMode sync_mode,
|
|
|
|
+ BdrvDirtyBitmap *bitmap,
|
|
|
|
+ BitmapSyncMode bitmap_mode,
|
|
|
|
+ BlockDriverState *base,
|
|
|
|
bool auto_complete, const char *filter_node_name,
|
|
|
|
bool is_mirror, MirrorCopyMode copy_mode,
|
|
|
|
Error **errp)
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1639,10 +1658,39 @@ static BlockJob *mirror_start_job(
|
2021-05-27 13:43:32 +03:00
|
|
|
uint64_t target_perms, target_shared_perms;
|
2020-03-17 10:55:24 +03:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
- if (granularity == 0) {
|
2022-06-27 14:05:40 +03:00
|
|
|
- granularity = bdrv_get_default_bitmap_granularity(target);
|
2020-03-17 10:55:24 +03:00
|
|
|
+ if (sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
|
|
|
|
+ error_setg(errp, "Sync mode '%s' not supported",
|
|
|
|
+ MirrorSyncMode_str(sync_mode));
|
|
|
|
+ return NULL;
|
|
|
|
+ } else if (sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
|
|
|
+ if (!bitmap) {
|
|
|
|
+ error_setg(errp, "Must provide a valid bitmap name for '%s'"
|
|
|
|
+ " sync mode",
|
|
|
|
+ MirrorSyncMode_str(sync_mode));
|
|
|
|
+ return NULL;
|
|
|
|
+ } else if (bitmap_mode != BITMAP_SYNC_MODE_NEVER) {
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "Bitmap Sync Mode '%s' is not supported by Mirror",
|
|
|
|
+ BitmapSyncMode_str(bitmap_mode));
|
|
|
|
+ }
|
|
|
|
+ } else if (bitmap) {
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "sync mode '%s' is not compatible with bitmaps",
|
|
|
|
+ MirrorSyncMode_str(sync_mode));
|
|
|
|
+ return NULL;
|
2022-06-27 14:05:40 +03:00
|
|
|
}
|
|
|
|
|
2020-03-17 10:55:24 +03:00
|
|
|
+ if (bitmap) {
|
|
|
|
+ if (granularity) {
|
|
|
|
+ error_setg(errp, "granularity (%d)"
|
|
|
|
+ "cannot be specified when a bitmap is provided",
|
|
|
|
+ granularity);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ granularity = bdrv_dirty_bitmap_granularity(bitmap);
|
|
|
|
+ } else if (granularity == 0) {
|
2022-06-27 14:05:40 +03:00
|
|
|
+ granularity = bdrv_get_default_bitmap_granularity(target);
|
|
|
|
+ }
|
2020-03-17 10:55:24 +03:00
|
|
|
assert(is_power_of_2(granularity));
|
|
|
|
|
|
|
|
if (buf_size < 0) {
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1774,7 +1822,9 @@ static BlockJob *mirror_start_job(
|
2020-03-17 10:55:24 +03:00
|
|
|
s->replaces = g_strdup(replaces);
|
|
|
|
s->on_source_error = on_source_error;
|
|
|
|
s->on_target_error = on_target_error;
|
|
|
|
- s->is_none_mode = is_none_mode;
|
|
|
|
+ s->sync_mode = sync_mode;
|
|
|
|
+ s->sync_bitmap = bitmap;
|
|
|
|
+ s->bitmap_mode = bitmap_mode;
|
|
|
|
s->backing_mode = backing_mode;
|
|
|
|
s->zero_target = zero_target;
|
|
|
|
s->copy_mode = copy_mode;
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1795,6 +1845,18 @@ static BlockJob *mirror_start_job(
|
2020-03-17 10:55:24 +03:00
|
|
|
bdrv_disable_dirty_bitmap(s->dirty_bitmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
+ if (s->sync_bitmap) {
|
|
|
|
+ bdrv_dirty_bitmap_set_busy(s->sync_bitmap, true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (s->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
|
|
|
+ bdrv_merge_dirty_bitmap(s->dirty_bitmap, s->sync_bitmap,
|
|
|
|
+ NULL, &local_err);
|
|
|
|
+ if (local_err) {
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
ret = block_job_add_bdrv(&s->common, "source", bs, 0,
|
|
|
|
BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE |
|
|
|
|
BLK_PERM_CONSISTENT_READ,
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1872,6 +1934,9 @@ fail:
|
2020-03-17 10:55:24 +03:00
|
|
|
if (s->dirty_bitmap) {
|
|
|
|
bdrv_release_dirty_bitmap(s->dirty_bitmap);
|
|
|
|
}
|
|
|
|
+ if (s->sync_bitmap) {
|
|
|
|
+ bdrv_dirty_bitmap_set_busy(s->sync_bitmap, false);
|
|
|
|
+ }
|
|
|
|
job_early_fail(&s->common.job);
|
|
|
|
}
|
|
|
|
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1889,31 +1954,25 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
2020-03-17 10:55:24 +03:00
|
|
|
BlockDriverState *target, const char *replaces,
|
|
|
|
int creation_flags, int64_t speed,
|
|
|
|
uint32_t granularity, int64_t buf_size,
|
|
|
|
- MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
|
|
|
|
+ MirrorSyncMode mode, BdrvDirtyBitmap *bitmap,
|
|
|
|
+ BitmapSyncMode bitmap_mode,
|
|
|
|
+ BlockMirrorBackingMode backing_mode,
|
|
|
|
bool zero_target,
|
|
|
|
BlockdevOnError on_source_error,
|
|
|
|
BlockdevOnError on_target_error,
|
|
|
|
bool unmap, const char *filter_node_name,
|
|
|
|
MirrorCopyMode copy_mode, Error **errp)
|
|
|
|
{
|
|
|
|
- bool is_none_mode;
|
|
|
|
BlockDriverState *base;
|
|
|
|
|
2022-06-27 14:05:40 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2020-03-17 10:55:24 +03:00
|
|
|
- if ((mode == MIRROR_SYNC_MODE_INCREMENTAL) ||
|
|
|
|
- (mode == MIRROR_SYNC_MODE_BITMAP)) {
|
|
|
|
- error_setg(errp, "Sync mode '%s' not supported",
|
|
|
|
- MirrorSyncMode_str(mode));
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
|
2021-02-11 19:11:11 +03:00
|
|
|
base = mode == MIRROR_SYNC_MODE_TOP ? bdrv_backing_chain_next(bs) : NULL;
|
2020-03-17 10:55:24 +03:00
|
|
|
mirror_start_job(job_id, bs, creation_flags, target, replaces,
|
|
|
|
speed, granularity, buf_size, backing_mode, zero_target,
|
|
|
|
on_source_error, on_target_error, unmap, NULL, NULL,
|
|
|
|
- &mirror_job_driver, is_none_mode, base, false,
|
|
|
|
- filter_node_name, true, copy_mode, errp);
|
|
|
|
+ &mirror_job_driver, mode, bitmap, bitmap_mode, base,
|
|
|
|
+ false, filter_node_name, true, copy_mode, errp);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -1940,7 +1999,8 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
2020-03-17 10:55:24 +03:00
|
|
|
job_id, bs, creation_flags, base, NULL, speed, 0, 0,
|
|
|
|
MIRROR_LEAVE_BACKING_CHAIN, false,
|
|
|
|
on_error, on_error, true, cb, opaque,
|
|
|
|
- &commit_active_job_driver, false, base, auto_complete,
|
|
|
|
+ &commit_active_job_driver, MIRROR_SYNC_MODE_FULL,
|
|
|
|
+ NULL, 0, base, auto_complete,
|
|
|
|
filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND,
|
2021-05-27 13:43:32 +03:00
|
|
|
errp);
|
|
|
|
if (!job) {
|
2020-03-17 10:55:24 +03:00
|
|
|
diff --git a/blockdev.c b/blockdev.c
|
2022-12-14 17:16:32 +03:00
|
|
|
index 3f1dec6242..2ee30323cb 100644
|
2020-03-17 10:55:24 +03:00
|
|
|
--- a/blockdev.c
|
|
|
|
+++ b/blockdev.c
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -2946,6 +2946,10 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
2020-03-17 10:55:24 +03:00
|
|
|
BlockDriverState *target,
|
|
|
|
bool has_replaces, const char *replaces,
|
|
|
|
enum MirrorSyncMode sync,
|
|
|
|
+ bool has_bitmap,
|
|
|
|
+ const char *bitmap_name,
|
|
|
|
+ bool has_bitmap_mode,
|
|
|
|
+ BitmapSyncMode bitmap_mode,
|
|
|
|
BlockMirrorBackingMode backing_mode,
|
|
|
|
bool zero_target,
|
|
|
|
bool has_speed, int64_t speed,
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -2965,6 +2969,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
2020-03-17 10:55:24 +03:00
|
|
|
{
|
2021-02-11 19:11:11 +03:00
|
|
|
BlockDriverState *unfiltered_bs;
|
2020-03-17 10:55:24 +03:00
|
|
|
int job_flags = JOB_DEFAULT;
|
|
|
|
+ BdrvDirtyBitmap *bitmap = NULL;
|
|
|
|
|
|
|
|
if (!has_speed) {
|
|
|
|
speed = 0;
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -3019,6 +3024,29 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
2020-03-17 10:55:24 +03:00
|
|
|
sync = MIRROR_SYNC_MODE_FULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ if (has_bitmap) {
|
|
|
|
+ if (granularity) {
|
|
|
|
+ error_setg(errp, "Granularity and bitmap cannot both be set");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!has_bitmap_mode) {
|
|
|
|
+ error_setg(errp, "bitmap-mode must be specified if"
|
|
|
|
+ " a bitmap is provided");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bitmap = bdrv_find_dirty_bitmap(bs, bitmap_name);
|
|
|
|
+ if (!bitmap) {
|
|
|
|
+ error_setg(errp, "Dirty bitmap '%s' not found", bitmap_name);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
2021-02-11 19:11:11 +03:00
|
|
|
if (!has_replaces) {
|
|
|
|
/* We want to mirror from @bs, but keep implicit filters on top */
|
|
|
|
unfiltered_bs = bdrv_skip_implicit_filters(bs);
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -3065,8 +3093,8 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
2020-03-17 10:55:24 +03:00
|
|
|
* and will allow to check whether the node still exist at mirror completion
|
|
|
|
*/
|
|
|
|
mirror_start(job_id, bs, target,
|
|
|
|
- has_replaces ? replaces : NULL, job_flags,
|
|
|
|
- speed, granularity, buf_size, sync, backing_mode, zero_target,
|
|
|
|
+ has_replaces ? replaces : NULL, job_flags, speed, granularity,
|
|
|
|
+ buf_size, sync, bitmap, bitmap_mode, backing_mode, zero_target,
|
|
|
|
on_source_error, on_target_error, unmap, filter_node_name,
|
|
|
|
copy_mode, errp);
|
|
|
|
}
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -3211,6 +3239,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
2020-03-17 10:55:24 +03:00
|
|
|
|
|
|
|
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
|
|
|
|
arg->has_replaces, arg->replaces, arg->sync,
|
|
|
|
+ arg->has_bitmap, arg->bitmap,
|
|
|
|
+ arg->has_bitmap_mode, arg->bitmap_mode,
|
|
|
|
backing_mode, zero_target,
|
|
|
|
arg->has_speed, arg->speed,
|
|
|
|
arg->has_granularity, arg->granularity,
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -3232,6 +3262,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
2020-03-17 10:55:24 +03:00
|
|
|
const char *device, const char *target,
|
|
|
|
bool has_replaces, const char *replaces,
|
|
|
|
MirrorSyncMode sync,
|
|
|
|
+ bool has_bitmap, const char *bitmap,
|
|
|
|
+ bool has_bitmap_mode, BitmapSyncMode bitmap_mode,
|
|
|
|
bool has_speed, int64_t speed,
|
|
|
|
bool has_granularity, uint32_t granularity,
|
|
|
|
bool has_buf_size, int64_t buf_size,
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -3281,7 +3313,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
2020-03-17 10:55:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
|
|
|
|
- has_replaces, replaces, sync, backing_mode,
|
|
|
|
+ has_replaces, replaces, sync, has_bitmap,
|
|
|
|
+ bitmap, has_bitmap_mode, bitmap_mode, backing_mode,
|
|
|
|
zero_target, has_speed, speed,
|
|
|
|
has_granularity, granularity,
|
|
|
|
has_buf_size, buf_size,
|
2022-06-27 14:05:40 +03:00
|
|
|
diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h
|
update submodule and patches to 7.1.0
Notable changes:
* The only big change is the switch to using a custom QIOChannel for
savevm-async, because the previously used QEMUFileOps was dropped.
Changes to the current implementation:
* Switch to vector based methods as required for an IO channel. For
short reads the passed-in IO vector is stuffed with zeroes at the
end, just to be sure.
* For reading: The documentation in include/io/channel.h states that
at least one byte should be read, so also error out when whe are
at the very end instead of returning 0.
* For reading: Fix off-by-one error when request goes beyond end.
The wrong code piece was:
if ((pos + size) > maxlen) {
size = maxlen - pos - 1;
}
Previously, the last byte would not be read. It's actually
possible to get a snapshot .raw file that has content all the way
up the final 512 byte (= BDRV_SECTOR_SIZE) boundary without any
trailing zero bytes (I wrote a script to do it).
Luckily, it didn't cause a real issue, because qemu_loadvm_state()
is not interested in the final (i.e. QEMU_VM_VMDESCRIPTION)
section. The buffer for reading it is simply freed up afterwards
and the function will assume that it read the whole section, even
if that's not the case.
* For writing: Make use of the generated blk_pwritev() wrapper
instead of manually wrapping the coroutine to simplify and save a
few lines.
* Adapt to changed interfaces for blk_{pread,pwrite}:
* a9262f551e ("block: Change blk_{pread,pwrite}() param order")
* 3b35d4542c ("block: Add a 'flags' param to blk_pread()")
* bf5b16fa40 ("block: Make blk_{pread,pwrite}() return 0 on success")
Those changes especially affected the qemu-img dd patches, because
the context also changed, but also some of our block drivers used
the functions.
* Drop qemu-common.h include: it got renamed after essentially
everything was moved to other headers. The only remaining user I
could find for things dropped from the header between 7.0 and 7.1
was qemu_get_vm_name() in the iscsi-initiatorname patch, but it
already includes the header to which the function was moved.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2022-10-14 15:07:13 +03:00
|
|
|
index b49f4eb35b..9d744db618 100644
|
2022-06-27 14:05:40 +03:00
|
|
|
--- a/include/block/block_int-global-state.h
|
|
|
|
+++ b/include/block/block_int-global-state.h
|
update submodule and patches to 7.1.0
Notable changes:
* The only big change is the switch to using a custom QIOChannel for
savevm-async, because the previously used QEMUFileOps was dropped.
Changes to the current implementation:
* Switch to vector based methods as required for an IO channel. For
short reads the passed-in IO vector is stuffed with zeroes at the
end, just to be sure.
* For reading: The documentation in include/io/channel.h states that
at least one byte should be read, so also error out when whe are
at the very end instead of returning 0.
* For reading: Fix off-by-one error when request goes beyond end.
The wrong code piece was:
if ((pos + size) > maxlen) {
size = maxlen - pos - 1;
}
Previously, the last byte would not be read. It's actually
possible to get a snapshot .raw file that has content all the way
up the final 512 byte (= BDRV_SECTOR_SIZE) boundary without any
trailing zero bytes (I wrote a script to do it).
Luckily, it didn't cause a real issue, because qemu_loadvm_state()
is not interested in the final (i.e. QEMU_VM_VMDESCRIPTION)
section. The buffer for reading it is simply freed up afterwards
and the function will assume that it read the whole section, even
if that's not the case.
* For writing: Make use of the generated blk_pwritev() wrapper
instead of manually wrapping the coroutine to simplify and save a
few lines.
* Adapt to changed interfaces for blk_{pread,pwrite}:
* a9262f551e ("block: Change blk_{pread,pwrite}() param order")
* 3b35d4542c ("block: Add a 'flags' param to blk_pread()")
* bf5b16fa40 ("block: Make blk_{pread,pwrite}() return 0 on success")
Those changes especially affected the qemu-img dd patches, because
the context also changed, but also some of our block drivers used
the functions.
* Drop qemu-common.h include: it got renamed after essentially
everything was moved to other headers. The only remaining user I
could find for things dropped from the header between 7.0 and 7.1
was qemu_get_vm_name() in the iscsi-initiatorname patch, but it
already includes the header to which the function was moved.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2022-10-14 15:07:13 +03:00
|
|
|
@@ -149,7 +149,9 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
2020-04-07 17:53:19 +03:00
|
|
|
BlockDriverState *target, const char *replaces,
|
|
|
|
int creation_flags, int64_t speed,
|
|
|
|
uint32_t granularity, int64_t buf_size,
|
|
|
|
- MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
|
|
|
|
+ MirrorSyncMode mode, BdrvDirtyBitmap *bitmap,
|
|
|
|
+ BitmapSyncMode bitmap_mode,
|
|
|
|
+ BlockMirrorBackingMode backing_mode,
|
|
|
|
bool zero_target,
|
|
|
|
BlockdevOnError on_source_error,
|
|
|
|
BlockdevOnError on_target_error,
|
2020-03-17 10:55:24 +03:00
|
|
|
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
2022-12-14 17:16:32 +03:00
|
|
|
index 95ac4fa634..7daaf545be 100644
|
2020-03-17 10:55:24 +03:00
|
|
|
--- a/qapi/block-core.json
|
|
|
|
+++ b/qapi/block-core.json
|
update submodule and patches to 7.1.0
Notable changes:
* The only big change is the switch to using a custom QIOChannel for
savevm-async, because the previously used QEMUFileOps was dropped.
Changes to the current implementation:
* Switch to vector based methods as required for an IO channel. For
short reads the passed-in IO vector is stuffed with zeroes at the
end, just to be sure.
* For reading: The documentation in include/io/channel.h states that
at least one byte should be read, so also error out when whe are
at the very end instead of returning 0.
* For reading: Fix off-by-one error when request goes beyond end.
The wrong code piece was:
if ((pos + size) > maxlen) {
size = maxlen - pos - 1;
}
Previously, the last byte would not be read. It's actually
possible to get a snapshot .raw file that has content all the way
up the final 512 byte (= BDRV_SECTOR_SIZE) boundary without any
trailing zero bytes (I wrote a script to do it).
Luckily, it didn't cause a real issue, because qemu_loadvm_state()
is not interested in the final (i.e. QEMU_VM_VMDESCRIPTION)
section. The buffer for reading it is simply freed up afterwards
and the function will assume that it read the whole section, even
if that's not the case.
* For writing: Make use of the generated blk_pwritev() wrapper
instead of manually wrapping the coroutine to simplify and save a
few lines.
* Adapt to changed interfaces for blk_{pread,pwrite}:
* a9262f551e ("block: Change blk_{pread,pwrite}() param order")
* 3b35d4542c ("block: Add a 'flags' param to blk_pread()")
* bf5b16fa40 ("block: Make blk_{pread,pwrite}() return 0 on success")
Those changes especially affected the qemu-img dd patches, because
the context also changed, but also some of our block drivers used
the functions.
* Drop qemu-common.h include: it got renamed after essentially
everything was moved to other headers. The only remaining user I
could find for things dropped from the header between 7.0 and 7.1
was qemu_get_vm_name() in the iscsi-initiatorname patch, but it
already includes the header to which the function was moved.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2022-10-14 15:07:13 +03:00
|
|
|
@@ -2000,10 +2000,19 @@
|
2020-03-17 10:55:24 +03:00
|
|
|
# (all the disk, only the sectors allocated in the topmost image, or
|
|
|
|
# only new I/O).
|
|
|
|
#
|
|
|
|
+# @bitmap: The name of a bitmap to use for sync=bitmap mode. This argument must
|
|
|
|
+# be present for bitmap mode and absent otherwise. The bitmap's
|
|
|
|
+# granularity is used instead of @granularity (since 4.1).
|
|
|
|
+#
|
|
|
|
+# @bitmap-mode: Specifies the type of data the bitmap should contain after
|
|
|
|
+# the operation concludes. Must be present if sync is "bitmap".
|
|
|
|
+# Must NOT be present otherwise. (Since 4.1)
|
|
|
|
+#
|
|
|
|
# @granularity: granularity of the dirty bitmap, default is 64K
|
|
|
|
# if the image format doesn't have clusters, 4K if the clusters
|
|
|
|
# are smaller than that, else the cluster size. Must be a
|
|
|
|
-# power of 2 between 512 and 64M (since 1.4).
|
|
|
|
+# power of 2 between 512 and 64M. Must not be specified if
|
|
|
|
+# @bitmap is present (since 1.4).
|
|
|
|
#
|
|
|
|
# @buf-size: maximum amount of data in flight from source to
|
|
|
|
# target (since 1.4).
|
update submodule and patches to 7.1.0
Notable changes:
* The only big change is the switch to using a custom QIOChannel for
savevm-async, because the previously used QEMUFileOps was dropped.
Changes to the current implementation:
* Switch to vector based methods as required for an IO channel. For
short reads the passed-in IO vector is stuffed with zeroes at the
end, just to be sure.
* For reading: The documentation in include/io/channel.h states that
at least one byte should be read, so also error out when whe are
at the very end instead of returning 0.
* For reading: Fix off-by-one error when request goes beyond end.
The wrong code piece was:
if ((pos + size) > maxlen) {
size = maxlen - pos - 1;
}
Previously, the last byte would not be read. It's actually
possible to get a snapshot .raw file that has content all the way
up the final 512 byte (= BDRV_SECTOR_SIZE) boundary without any
trailing zero bytes (I wrote a script to do it).
Luckily, it didn't cause a real issue, because qemu_loadvm_state()
is not interested in the final (i.e. QEMU_VM_VMDESCRIPTION)
section. The buffer for reading it is simply freed up afterwards
and the function will assume that it read the whole section, even
if that's not the case.
* For writing: Make use of the generated blk_pwritev() wrapper
instead of manually wrapping the coroutine to simplify and save a
few lines.
* Adapt to changed interfaces for blk_{pread,pwrite}:
* a9262f551e ("block: Change blk_{pread,pwrite}() param order")
* 3b35d4542c ("block: Add a 'flags' param to blk_pread()")
* bf5b16fa40 ("block: Make blk_{pread,pwrite}() return 0 on success")
Those changes especially affected the qemu-img dd patches, because
the context also changed, but also some of our block drivers used
the functions.
* Drop qemu-common.h include: it got renamed after essentially
everything was moved to other headers. The only remaining user I
could find for things dropped from the header between 7.0 and 7.1
was qemu_get_vm_name() in the iscsi-initiatorname patch, but it
already includes the header to which the function was moved.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2022-10-14 15:07:13 +03:00
|
|
|
@@ -2043,7 +2052,9 @@
|
2020-03-17 10:55:24 +03:00
|
|
|
{ 'struct': 'DriveMirror',
|
|
|
|
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
|
|
|
|
'*format': 'str', '*node-name': 'str', '*replaces': 'str',
|
|
|
|
- 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
|
|
|
|
+ 'sync': 'MirrorSyncMode', '*bitmap': 'str',
|
|
|
|
+ '*bitmap-mode': 'BitmapSyncMode',
|
|
|
|
+ '*mode': 'NewImageMode',
|
|
|
|
'*speed': 'int', '*granularity': 'uint32',
|
|
|
|
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
|
|
|
|
'*on-target-error': 'BlockdevOnError',
|
update submodule and patches to 7.1.0
Notable changes:
* The only big change is the switch to using a custom QIOChannel for
savevm-async, because the previously used QEMUFileOps was dropped.
Changes to the current implementation:
* Switch to vector based methods as required for an IO channel. For
short reads the passed-in IO vector is stuffed with zeroes at the
end, just to be sure.
* For reading: The documentation in include/io/channel.h states that
at least one byte should be read, so also error out when whe are
at the very end instead of returning 0.
* For reading: Fix off-by-one error when request goes beyond end.
The wrong code piece was:
if ((pos + size) > maxlen) {
size = maxlen - pos - 1;
}
Previously, the last byte would not be read. It's actually
possible to get a snapshot .raw file that has content all the way
up the final 512 byte (= BDRV_SECTOR_SIZE) boundary without any
trailing zero bytes (I wrote a script to do it).
Luckily, it didn't cause a real issue, because qemu_loadvm_state()
is not interested in the final (i.e. QEMU_VM_VMDESCRIPTION)
section. The buffer for reading it is simply freed up afterwards
and the function will assume that it read the whole section, even
if that's not the case.
* For writing: Make use of the generated blk_pwritev() wrapper
instead of manually wrapping the coroutine to simplify and save a
few lines.
* Adapt to changed interfaces for blk_{pread,pwrite}:
* a9262f551e ("block: Change blk_{pread,pwrite}() param order")
* 3b35d4542c ("block: Add a 'flags' param to blk_pread()")
* bf5b16fa40 ("block: Make blk_{pread,pwrite}() return 0 on success")
Those changes especially affected the qemu-img dd patches, because
the context also changed, but also some of our block drivers used
the functions.
* Drop qemu-common.h include: it got renamed after essentially
everything was moved to other headers. The only remaining user I
could find for things dropped from the header between 7.0 and 7.1
was qemu_get_vm_name() in the iscsi-initiatorname patch, but it
already includes the header to which the function was moved.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2022-10-14 15:07:13 +03:00
|
|
|
@@ -2322,10 +2333,19 @@
|
2020-03-17 10:55:24 +03:00
|
|
|
# (all the disk, only the sectors allocated in the topmost image, or
|
|
|
|
# only new I/O).
|
|
|
|
#
|
|
|
|
+# @bitmap: The name of a bitmap to use for sync=bitmap mode. This argument must
|
|
|
|
+# be present for bitmap mode and absent otherwise. The bitmap's
|
|
|
|
+# granularity is used instead of @granularity (since 4.1).
|
|
|
|
+#
|
|
|
|
+# @bitmap-mode: Specifies the type of data the bitmap should contain after
|
|
|
|
+# the operation concludes. Must be present if sync is "bitmap".
|
|
|
|
+# Must NOT be present otherwise. (Since 4.1)
|
|
|
|
+#
|
|
|
|
# @granularity: granularity of the dirty bitmap, default is 64K
|
|
|
|
# if the image format doesn't have clusters, 4K if the clusters
|
|
|
|
# are smaller than that, else the cluster size. Must be a
|
|
|
|
-# power of 2 between 512 and 64M
|
|
|
|
+# power of 2 between 512 and 64M . Must not be specified if
|
|
|
|
+# @bitmap is present.
|
|
|
|
#
|
|
|
|
# @buf-size: maximum amount of data in flight from source to
|
|
|
|
# target
|
update submodule and patches to 7.1.0
Notable changes:
* The only big change is the switch to using a custom QIOChannel for
savevm-async, because the previously used QEMUFileOps was dropped.
Changes to the current implementation:
* Switch to vector based methods as required for an IO channel. For
short reads the passed-in IO vector is stuffed with zeroes at the
end, just to be sure.
* For reading: The documentation in include/io/channel.h states that
at least one byte should be read, so also error out when whe are
at the very end instead of returning 0.
* For reading: Fix off-by-one error when request goes beyond end.
The wrong code piece was:
if ((pos + size) > maxlen) {
size = maxlen - pos - 1;
}
Previously, the last byte would not be read. It's actually
possible to get a snapshot .raw file that has content all the way
up the final 512 byte (= BDRV_SECTOR_SIZE) boundary without any
trailing zero bytes (I wrote a script to do it).
Luckily, it didn't cause a real issue, because qemu_loadvm_state()
is not interested in the final (i.e. QEMU_VM_VMDESCRIPTION)
section. The buffer for reading it is simply freed up afterwards
and the function will assume that it read the whole section, even
if that's not the case.
* For writing: Make use of the generated blk_pwritev() wrapper
instead of manually wrapping the coroutine to simplify and save a
few lines.
* Adapt to changed interfaces for blk_{pread,pwrite}:
* a9262f551e ("block: Change blk_{pread,pwrite}() param order")
* 3b35d4542c ("block: Add a 'flags' param to blk_pread()")
* bf5b16fa40 ("block: Make blk_{pread,pwrite}() return 0 on success")
Those changes especially affected the qemu-img dd patches, because
the context also changed, but also some of our block drivers used
the functions.
* Drop qemu-common.h include: it got renamed after essentially
everything was moved to other headers. The only remaining user I
could find for things dropped from the header between 7.0 and 7.1
was qemu_get_vm_name() in the iscsi-initiatorname patch, but it
already includes the header to which the function was moved.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2022-10-14 15:07:13 +03:00
|
|
|
@@ -2375,7 +2395,8 @@
|
2020-03-17 10:55:24 +03:00
|
|
|
{ 'command': 'blockdev-mirror',
|
|
|
|
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
|
|
|
|
'*replaces': 'str',
|
|
|
|
- 'sync': 'MirrorSyncMode',
|
|
|
|
+ 'sync': 'MirrorSyncMode', '*bitmap': 'str',
|
|
|
|
+ '*bitmap-mode': 'BitmapSyncMode',
|
|
|
|
'*speed': 'int', '*granularity': 'uint32',
|
|
|
|
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
|
|
|
|
'*on-target-error': 'BlockdevOnError',
|
2021-05-27 13:43:32 +03:00
|
|
|
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
|
2022-12-14 17:16:32 +03:00
|
|
|
index 8ca5adec5e..dae80e5a5f 100644
|
2021-05-27 13:43:32 +03:00
|
|
|
--- a/tests/unit/test-block-iothread.c
|
|
|
|
+++ b/tests/unit/test-block-iothread.c
|
2022-12-14 17:16:32 +03:00
|
|
|
@@ -755,8 +755,8 @@ static void test_propagate_mirror(void)
|
2020-04-07 17:53:19 +03:00
|
|
|
|
|
|
|
/* Start a mirror job */
|
|
|
|
mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0,
|
|
|
|
- MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false,
|
|
|
|
- BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
|
|
|
|
+ MIRROR_SYNC_MODE_NONE, NULL, 0, MIRROR_OPEN_BACKING_CHAIN,
|
|
|
|
+ false, BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
|
|
|
|
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
|
|
|
|
&error_abort);
|
2022-12-14 17:16:32 +03:00
|
|
|
WITH_JOB_LOCK_GUARD() {
|