Signed-off-by: John Snow <jsnow@redhat.com>
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
-[FE: rebased for 8.0]
+[FE: rebased for 8.1.1]
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
block/mirror.c | 98 +++++++++++++++++++++-----
blockdev.c | 38 +++++++++-
include/block/block_int-global-state.h | 4 +-
- qapi/block-core.json | 29 ++++++--
+ qapi/block-core.json | 25 ++++++-
tests/unit/test-block-iothread.c | 4 +-
- 5 files changed, 144 insertions(+), 29 deletions(-)
+ 5 files changed, 142 insertions(+), 27 deletions(-)
diff --git a/block/mirror.c b/block/mirror.c
-index 663e2b7002..9099c75992 100644
+index d3cacd1708..1ff42c8af1 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -51,7 +51,7 @@ typedef struct MirrorBlockJob {
BdrvDirtyBitmap *dirty_bitmap;
BdrvDirtyBitmapIter *dbi;
uint8_t *buf;
-@@ -703,7 +705,8 @@ static int mirror_exit_common(Job *job)
+@@ -705,7 +707,8 @@ static int mirror_exit_common(Job *job)
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
&error_abort);
if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {
BlockDriverState *unfiltered_target = bdrv_skip_filters(target_bs);
if (bdrv_cow_bs(unfiltered_target) != backing) {
-@@ -801,6 +804,16 @@ static void mirror_abort(Job *job)
+@@ -809,6 +812,16 @@ static void mirror_abort(Job *job)
assert(ret == 0);
}
static void coroutine_fn mirror_throttle(MirrorBlockJob *s)
{
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-@@ -987,7 +1000,8 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
+@@ -997,7 +1010,8 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
mirror_free_init(s);
s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
ret = mirror_dirty_init(s);
if (ret < 0 || job_is_cancelled(&s->common.job)) {
goto immediate_exit;
-@@ -1240,6 +1254,7 @@ static const BlockJobDriver mirror_job_driver = {
+@@ -1251,6 +1265,7 @@ static const BlockJobDriver mirror_job_driver = {
.run = mirror_run,
.prepare = mirror_prepare,
.abort = mirror_abort,
.pause = mirror_pause,
.complete = mirror_complete,
.cancel = mirror_cancel,
-@@ -1256,6 +1271,7 @@ static const BlockJobDriver commit_active_job_driver = {
+@@ -1267,6 +1282,7 @@ static const BlockJobDriver commit_active_job_driver = {
.run = mirror_run,
.prepare = mirror_prepare,
.abort = mirror_abort,
.pause = mirror_pause,
.complete = mirror_complete,
.cancel = commit_active_cancel,
-@@ -1647,7 +1663,10 @@ static BlockJob *mirror_start_job(
+@@ -1658,7 +1674,10 @@ static BlockJob *mirror_start_job(
BlockCompletionFunc *cb,
void *opaque,
const BlockJobDriver *driver,
bool auto_complete, const char *filter_node_name,
bool is_mirror, MirrorCopyMode copy_mode,
Error **errp)
-@@ -1659,10 +1678,39 @@ static BlockJob *mirror_start_job(
+@@ -1670,10 +1689,39 @@ static BlockJob *mirror_start_job(
uint64_t target_perms, target_shared_perms;
int ret;
assert(is_power_of_2(granularity));
if (buf_size < 0) {
-@@ -1793,7 +1841,9 @@ static BlockJob *mirror_start_job(
+@@ -1804,7 +1852,9 @@ static BlockJob *mirror_start_job(
s->replaces = g_strdup(replaces);
s->on_source_error = on_source_error;
s->on_target_error = on_target_error;
s->backing_mode = backing_mode;
s->zero_target = zero_target;
s->copy_mode = copy_mode;
-@@ -1814,6 +1864,18 @@ static BlockJob *mirror_start_job(
+@@ -1825,6 +1875,18 @@ static BlockJob *mirror_start_job(
bdrv_disable_dirty_bitmap(s->dirty_bitmap);
}
ret = block_job_add_bdrv(&s->common, "source", bs, 0,
BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE |
BLK_PERM_CONSISTENT_READ,
-@@ -1891,6 +1953,9 @@ fail:
+@@ -1902,6 +1964,9 @@ fail:
if (s->dirty_bitmap) {
bdrv_release_dirty_bitmap(s->dirty_bitmap);
}
job_early_fail(&s->common.job);
}
-@@ -1908,31 +1973,25 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
+@@ -1919,31 +1984,25 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
BlockDriverState *target, const char *replaces,
int creation_flags, int64_t speed,
uint32_t granularity, int64_t buf_size,
}
BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
-@@ -1959,7 +2018,8 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
+@@ -1970,7 +2029,8 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
job_id, bs, creation_flags, base, NULL, speed, 0, 0,
MIRROR_LEAVE_BACKING_CHAIN, false,
on_error, on_error, true, cb, opaque,
errp);
if (!job) {
diff --git a/blockdev.c b/blockdev.c
-index e464daea58..50e4a9c682 100644
+index e6eba61484..a8b1fd2a73 100644
--- a/blockdev.c
+++ b/blockdev.c
-@@ -2942,6 +2942,9 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2848,6 +2848,9 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
BlockDriverState *target,
const char *replaces,
enum MirrorSyncMode sync,
BlockMirrorBackingMode backing_mode,
bool zero_target,
bool has_speed, int64_t speed,
-@@ -2960,6 +2963,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2866,6 +2869,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
{
BlockDriverState *unfiltered_bs;
int job_flags = JOB_DEFAULT;
+ BdrvDirtyBitmap *bitmap = NULL;
- if (!has_speed) {
- speed = 0;
-@@ -3011,6 +3015,29 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+@@ -2920,6 +2924,29 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
sync = MIRROR_SYNC_MODE_FULL;
}
if (!replaces) {
/* We want to mirror from @bs, but keep implicit filters on top */
unfiltered_bs = bdrv_skip_implicit_filters(bs);
-@@ -3056,8 +3083,8 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2965,8 +2992,8 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
* and will allow to check whether the node still exist at mirror completion
*/
mirror_start(job_id, bs, target,
on_source_error, on_target_error, unmap, filter_node_name,
copy_mode, errp);
}
-@@ -3202,6 +3229,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
+@@ -3114,6 +3141,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
blockdev_mirror_common(arg->job_id, bs, target_bs,
arg->replaces, arg->sync,
backing_mode, zero_target,
arg->has_speed, arg->speed,
arg->has_granularity, arg->granularity,
-@@ -3223,6 +3252,8 @@ void qmp_blockdev_mirror(const char *job_id,
+@@ -3135,6 +3164,8 @@ void qmp_blockdev_mirror(const char *job_id,
const char *device, const char *target,
const char *replaces,
MirrorSyncMode sync,
bool has_speed, int64_t speed,
bool has_granularity, uint32_t granularity,
bool has_buf_size, int64_t buf_size,
-@@ -3271,7 +3302,8 @@ void qmp_blockdev_mirror(const char *job_id,
+@@ -3183,7 +3214,8 @@ void qmp_blockdev_mirror(const char *job_id,
}
blockdev_mirror_common(job_id, bs, target_bs,
has_granularity, granularity,
has_buf_size, buf_size,
diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h
-index 902406eb99..d559be928c 100644
+index da5fb31089..32f0f9858a 100644
--- a/include/block/block_int-global-state.h
+++ b/include/block/block_int-global-state.h
@@ -152,7 +152,9 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index c05ad0c07e..3c945c1f93 100644
+index 2b1d493d6e..903392cb8f 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -2095,10 +2095,19 @@
- # (all the disk, only the sectors allocated in the topmost image, or
- # only new I/O).
+@@ -2145,6 +2145,15 @@
+ # destination (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: 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)
++# @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).
-@@ -2138,7 +2147,9 @@
+ # @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
+@@ -2187,7 +2196,9 @@
{ 'struct': 'DriveMirror',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
'*format': 'str', '*node-name': 'str', '*replaces': 'str',
'*speed': 'int', '*granularity': 'uint32',
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError',
-@@ -2417,10 +2428,19 @@
- # (all the disk, only the sectors allocated in the topmost image, or
- # only new I/O).
+@@ -2471,6 +2482,15 @@
+ # destination (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: 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)
++# @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
-@@ -2470,7 +2490,8 @@
+ # @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
+@@ -2521,7 +2541,8 @@
{ 'command': 'blockdev-mirror',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
'*replaces': 'str',
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError',
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
-index 3a5e1eb2c4..c1ecc49073 100644
+index d727a5fee8..8a34aa2328 100644
--- a/tests/unit/test-block-iothread.c
+++ b/tests/unit/test-block-iothread.c
@@ -757,8 +757,8 @@ static void test_propagate_mirror(void)