From: @kuhnchen18 Reviewed-by: @imxcc Signed-off-by: @imxcc
This commit is contained in:
commit
3228f21737
78
block-Fix-cross-AioContext-blockdev-snapshot.patch
Normal file
78
block-Fix-cross-AioContext-blockdev-snapshot.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From ec96b9f64c239736003413d70dc3999ad0b8271c Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 10 Mar 2020 12:38:29 +0100
|
||||
Subject: [PATCH] block: Fix cross-AioContext blockdev-snapshot
|
||||
|
||||
external_snapshot_prepare() tries to move the overlay to the AioContext
|
||||
of the backing file (the snapshotted node). However, it's possible that
|
||||
this doesn't work, but the backing file can instead be moved to the
|
||||
overlay's AioContext (e.g. opening the backing chain for a mirror
|
||||
target).
|
||||
|
||||
bdrv_append() already indirectly uses bdrv_attach_node(), which takes
|
||||
care to move nodes to make sure they use the same AioContext and which
|
||||
tries both directions.
|
||||
|
||||
So the problem has a simple fix: Just delete the unnecessary extra
|
||||
bdrv_try_set_aio_context() call in external_snapshot_prepare() and
|
||||
instead assert in bdrv_append() that both nodes were indeed moved to the
|
||||
same AioContext.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-Id: <20200310113831.27293-6-kwolf@redhat.com>
|
||||
Tested-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
block.c | 1 +
|
||||
blockdev.c | 16 ----------------
|
||||
2 files changed, 1 insertion(+), 16 deletions(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index ba36b53a00..824025f781 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -4165,6 +4165,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
|
||||
bdrv_ref(from);
|
||||
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
+ assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to));
|
||||
bdrv_drained_begin(from);
|
||||
|
||||
/* Put all parents into @list and calculate their cumulative permissions */
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 79112be2e6..d1a3b6a630 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -1578,8 +1578,6 @@ static void external_snapshot_prepare(BlkActionState *common,
|
||||
DO_UPCAST(ExternalSnapshotState, common, common);
|
||||
TransactionAction *action = common->action;
|
||||
AioContext *aio_context;
|
||||
- AioContext *old_context;
|
||||
- int ret;
|
||||
|
||||
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
|
||||
* purpose but a different set of parameters */
|
||||
@@ -1719,20 +1717,6 @@ static void external_snapshot_prepare(BlkActionState *common,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
||||
- old_context = bdrv_get_aio_context(state->new_bs);
|
||||
- aio_context_release(aio_context);
|
||||
- aio_context_acquire(old_context);
|
||||
-
|
||||
- ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
|
||||
-
|
||||
- aio_context_release(old_context);
|
||||
- aio_context_acquire(aio_context);
|
||||
-
|
||||
- if (ret < 0) {
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
/* This removes our old bs and adds the new bs. This is an operation that
|
||||
* can fail, so we need to do it in .prepare; undoing it for abort is
|
||||
* always possible. */
|
||||
--
|
||||
2.27.0
|
||||
|
||||
252
block-backup-Add-mirror-sync-mode-bitmap.patch
Normal file
252
block-backup-Add-mirror-sync-mode-bitmap.patch
Normal file
@ -0,0 +1,252 @@
|
||||
From e0a0150e671e8129f11aa3df907e444e91711f53 Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:52 -0400
|
||||
Subject: [PATCH] block/backup: Add mirror sync mode 'bitmap'
|
||||
|
||||
We don't need or want a new sync mode for simple differences in
|
||||
semantics. Create a new mode simply named "BITMAP" that is designed to
|
||||
make use of the new Bitmap Sync Mode field.
|
||||
|
||||
Because the only bitmap sync mode is 'on-success', this adds no new
|
||||
functionality to the backup job (yet). The old incremental backup mode
|
||||
is maintained as a syntactic sugar for sync=bitmap, mode=on-success.
|
||||
|
||||
Add all of the plumbing necessary to support this new instruction.
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190709232550.10724-6-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
block/backup.c | 20 ++++++++++++--------
|
||||
block/mirror.c | 6 ++++--
|
||||
block/replication.c | 2 +-
|
||||
blockdev.c | 25 +++++++++++++++++++++++--
|
||||
include/block/block_int.h | 4 +++-
|
||||
qapi/block-core.json | 21 +++++++++++++++------
|
||||
6 files changed, 58 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/block/backup.c b/block/backup.c
|
||||
index 88354dcb32..e37eda80cd 100644
|
||||
--- a/block/backup.c
|
||||
+++ b/block/backup.c
|
||||
@@ -38,9 +38,9 @@ typedef struct CowRequest {
|
||||
typedef struct BackupBlockJob {
|
||||
BlockJob common;
|
||||
BlockBackend *target;
|
||||
- /* bitmap for sync=incremental */
|
||||
BdrvDirtyBitmap *sync_bitmap;
|
||||
MirrorSyncMode sync_mode;
|
||||
+ BitmapSyncMode bitmap_mode;
|
||||
BlockdevOnError on_source_error;
|
||||
BlockdevOnError on_target_error;
|
||||
CoRwlock flush_rwlock;
|
||||
@@ -461,7 +461,7 @@ static int coroutine_fn backup_run(Job *job, Error **errp)
|
||||
|
||||
job_progress_set_remaining(job, s->len);
|
||||
|
||||
- if (s->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
|
||||
+ if (s->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
||||
backup_incremental_init_copy_bitmap(s);
|
||||
} else {
|
||||
hbitmap_set(s->copy_bitmap, 0, s->len);
|
||||
@@ -545,6 +545,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target,
|
||||
BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *target, int64_t speed,
|
||||
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
||||
+ BitmapSyncMode bitmap_mode,
|
||||
bool compress,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
@@ -592,10 +593,13 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
|
||||
+ /* QMP interface should have handled translating this to bitmap mode */
|
||||
+ assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
|
||||
+
|
||||
+ if (sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
||||
if (!sync_bitmap) {
|
||||
error_setg(errp, "must provide a valid bitmap name for "
|
||||
- "\"incremental\" sync mode");
|
||||
+ "'%s' sync mode", MirrorSyncMode_str(sync_mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -605,8 +609,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
}
|
||||
} else if (sync_bitmap) {
|
||||
error_setg(errp,
|
||||
- "a sync_bitmap was provided to backup_run, "
|
||||
- "but received an incompatible sync_mode (%s)",
|
||||
+ "a bitmap was given to backup_job_create, "
|
||||
+ "but it received an incompatible sync_mode (%s)",
|
||||
MirrorSyncMode_str(sync_mode));
|
||||
return NULL;
|
||||
}
|
||||
@@ -648,8 +652,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
job->on_source_error = on_source_error;
|
||||
job->on_target_error = on_target_error;
|
||||
job->sync_mode = sync_mode;
|
||||
- job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
|
||||
- sync_bitmap : NULL;
|
||||
+ job->sync_bitmap = sync_bitmap;
|
||||
+ job->bitmap_mode = bitmap_mode;
|
||||
job->compress = compress;
|
||||
|
||||
/* Detect image-fleecing (and similar) schemes */
|
||||
diff --git a/block/mirror.c b/block/mirror.c
|
||||
index abcf60a961..ccae49a28e 100644
|
||||
--- a/block/mirror.c
|
||||
+++ b/block/mirror.c
|
||||
@@ -1770,8 +1770,10 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
bool is_none_mode;
|
||||
BlockDriverState *base;
|
||||
|
||||
- if (mode == MIRROR_SYNC_MODE_INCREMENTAL) {
|
||||
- error_setg(errp, "Sync mode 'incremental' not supported");
|
||||
+ 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;
|
||||
diff --git a/block/replication.c b/block/replication.c
|
||||
index 23b2993d74..936b2f8b5a 100644
|
||||
--- a/block/replication.c
|
||||
+++ b/block/replication.c
|
||||
@@ -543,7 +543,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
|
||||
s->backup_job = backup_job_create(
|
||||
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
|
||||
- 0, MIRROR_SYNC_MODE_NONE, NULL, false,
|
||||
+ 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false,
|
||||
BLOCKDEV_ON_ERROR_REPORT,
|
||||
BLOCKDEV_ON_ERROR_REPORT, JOB_INTERNAL,
|
||||
backup_job_completed, bs, NULL, &local_err);
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index aa15ed1f00..34c8b651e1 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3508,12 +3508,31 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ if (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL) {
|
||||
+ if (backup->has_bitmap_mode &&
|
||||
+ backup->bitmap_mode != BITMAP_SYNC_MODE_ON_SUCCESS) {
|
||||
+ error_setg(errp, "Bitmap sync mode must be '%s' "
|
||||
+ "when using sync mode '%s'",
|
||||
+ BitmapSyncMode_str(BITMAP_SYNC_MODE_ON_SUCCESS),
|
||||
+ MirrorSyncMode_str(backup->sync));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ backup->has_bitmap_mode = true;
|
||||
+ backup->sync = MIRROR_SYNC_MODE_BITMAP;
|
||||
+ backup->bitmap_mode = BITMAP_SYNC_MODE_ON_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
if (backup->has_bitmap) {
|
||||
bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
|
||||
if (!bmap) {
|
||||
error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
|
||||
return NULL;
|
||||
}
|
||||
+ if (!backup->has_bitmap_mode) {
|
||||
+ error_setg(errp, "Bitmap sync mode must be given "
|
||||
+ "when providing a bitmap");
|
||||
+ return NULL;
|
||||
+ }
|
||||
if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -3527,8 +3546,10 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
}
|
||||
|
||||
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
- backup->sync, bmap, backup->compress,
|
||||
- backup->on_source_error, backup->on_target_error,
|
||||
+ backup->sync, bmap, backup->bitmap_mode,
|
||||
+ backup->compress,
|
||||
+ backup->on_source_error,
|
||||
+ backup->on_target_error,
|
||||
job_flags, NULL, NULL, txn, errp);
|
||||
return job;
|
||||
}
|
||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
||||
index 05ee6b4866..76117a761a 100644
|
||||
--- a/include/block/block_int.h
|
||||
+++ b/include/block/block_int.h
|
||||
@@ -1152,7 +1152,8 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
* @target: Block device to write to.
|
||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
||||
* @sync_mode: What parts of the disk image should be copied to the destination.
|
||||
- * @sync_bitmap: The dirty bitmap if sync_mode is MIRROR_SYNC_MODE_INCREMENTAL.
|
||||
+ * @sync_bitmap: The dirty bitmap if sync_mode is 'bitmap' or 'incremental'
|
||||
+ * @bitmap_mode: The bitmap synchronization policy to use.
|
||||
* @on_source_error: The action to take upon error reading from the source.
|
||||
* @on_target_error: The action to take upon error writing to the target.
|
||||
* @creation_flags: Flags that control the behavior of the Job lifetime.
|
||||
@@ -1168,6 +1169,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *target, int64_t speed,
|
||||
MirrorSyncMode sync_mode,
|
||||
BdrvDirtyBitmap *sync_bitmap,
|
||||
+ BitmapSyncMode bitmap_mode,
|
||||
bool compress,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
||||
index b8d12a4951..97baff3a8c 100644
|
||||
--- a/qapi/block-core.json
|
||||
+++ b/qapi/block-core.json
|
||||
@@ -1127,12 +1127,15 @@
|
||||
#
|
||||
# @none: only copy data written from now on
|
||||
#
|
||||
-# @incremental: only copy data described by the dirty bitmap. Since: 2.4
|
||||
+# @incremental: only copy data described by the dirty bitmap. (since: 2.4)
|
||||
+#
|
||||
+# @bitmap: only copy data described by the dirty bitmap. (since: 4.2)
|
||||
+# Behavior on completion is determined by the BitmapSyncMode.
|
||||
#
|
||||
# Since: 1.3
|
||||
##
|
||||
{ 'enum': 'MirrorSyncMode',
|
||||
- 'data': ['top', 'full', 'none', 'incremental'] }
|
||||
+ 'data': ['top', 'full', 'none', 'incremental', 'bitmap'] }
|
||||
|
||||
##
|
||||
# @BitmapSyncMode:
|
||||
@@ -1343,9 +1346,14 @@
|
||||
# @speed: the maximum speed, in bytes per second. The default is 0,
|
||||
# for unlimited.
|
||||
#
|
||||
-# @bitmap: the name of dirty bitmap if sync is "incremental".
|
||||
-# Must be present if sync is "incremental", must NOT be present
|
||||
-# otherwise. (Since 2.4 (drive-backup), 3.1 (blockdev-backup))
|
||||
+# @bitmap: the name of a dirty bitmap if sync is "bitmap" or "incremental".
|
||||
+# Must be present if sync is "bitmap" or "incremental".
|
||||
+# Must not be present otherwise.
|
||||
+# (Since 2.4 (drive-backup), 3.1 (blockdev-backup))
|
||||
+#
|
||||
+# @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.2)
|
||||
#
|
||||
# @compress: true to compress data, if the target format supports it.
|
||||
# (default: false) (since 2.8)
|
||||
@@ -1380,7 +1388,8 @@
|
||||
{ 'struct': 'BackupCommon',
|
||||
'data': { '*job-id': 'str', 'device': 'str',
|
||||
'sync': 'MirrorSyncMode', '*speed': 'int',
|
||||
- '*bitmap': 'str', '*compress': 'bool',
|
||||
+ '*bitmap': 'str', '*bitmap-mode': 'BitmapSyncMode',
|
||||
+ '*compress': 'bool',
|
||||
'*on-source-error': 'BlockdevOnError',
|
||||
'*on-target-error': 'BlockdevOnError',
|
||||
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
|
||||
--
|
||||
2.27.0
|
||||
|
||||
59
block-backup-add-never-policy-to-bitmap-sync-mode.patch
Normal file
59
block-backup-add-never-policy-to-bitmap-sync-mode.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 98ed0f915cf3335768ed84ee5dfa54f4e99aaf00 Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:53 -0400
|
||||
Subject: [PATCH] block/backup: add 'never' policy to bitmap sync mode
|
||||
|
||||
This adds a "never" policy for bitmap synchronization. Regardless of if
|
||||
the job succeeds or fails, we never update the bitmap. This can be used
|
||||
to perform differential backups, or simply to avoid the job modifying a
|
||||
bitmap.
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190709232550.10724-7-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
block/backup.c | 7 +++++--
|
||||
qapi/block-core.json | 5 ++++-
|
||||
2 files changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/block/backup.c b/block/backup.c
|
||||
index e37eda80cd..84a56337ac 100644
|
||||
--- a/block/backup.c
|
||||
+++ b/block/backup.c
|
||||
@@ -274,8 +274,11 @@ static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
|
||||
BdrvDirtyBitmap *bm;
|
||||
BlockDriverState *bs = blk_bs(job->common.blk);
|
||||
|
||||
- if (ret < 0) {
|
||||
- /* Merge the successor back into the parent, delete nothing. */
|
||||
+ if (ret < 0 || job->bitmap_mode == BITMAP_SYNC_MODE_NEVER) {
|
||||
+ /*
|
||||
+ * Failure, or we don't want to synchronize the bitmap.
|
||||
+ * Merge the successor back into the parent, delete nothing.
|
||||
+ */
|
||||
bm = bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL);
|
||||
assert(bm);
|
||||
} else {
|
||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
||||
index 97baff3a8c..48a0bfab63 100644
|
||||
--- a/qapi/block-core.json
|
||||
+++ b/qapi/block-core.json
|
||||
@@ -1146,10 +1146,13 @@
|
||||
# @on-success: The bitmap is only synced when the operation is successful.
|
||||
# This is the behavior always used for 'INCREMENTAL' backups.
|
||||
#
|
||||
+# @never: The bitmap is never synchronized with the operation, and is
|
||||
+# treated solely as a read-only manifest of blocks to copy.
|
||||
+#
|
||||
# Since: 4.2
|
||||
##
|
||||
{ 'enum': 'BitmapSyncMode',
|
||||
- 'data': ['on-success'] }
|
||||
+ 'data': ['on-success', 'never'] }
|
||||
|
||||
##
|
||||
# @MirrorCopyMode:
|
||||
--
|
||||
2.27.0
|
||||
|
||||
83
block-backup-deal-with-zero-detection.patch
Normal file
83
block-backup-deal-with-zero-detection.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From 3cf14b9a7daf0a40eb2af7a86e67cb05f6d2bea6 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Date: Tue, 30 Jul 2019 19:32:49 +0300
|
||||
Subject: [PATCH] block/backup: deal with zero detection
|
||||
|
||||
We have detect_zeroes option, so at least for blockdev-backup user
|
||||
should define it if zero-detection is needed. For drive-backup leave
|
||||
detection enabled by default but do it through existing option instead
|
||||
of open-coding.
|
||||
|
||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190730163251.755248-2-vsementsov@virtuozzo.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
block/backup.c | 15 ++++++---------
|
||||
blockdev.c | 8 ++++----
|
||||
2 files changed, 10 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/block/backup.c b/block/backup.c
|
||||
index cc19643b47..6023573299 100644
|
||||
--- a/block/backup.c
|
||||
+++ b/block/backup.c
|
||||
@@ -110,7 +110,10 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
|
||||
BlockBackend *blk = job->common.blk;
|
||||
int nbytes;
|
||||
int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
|
||||
- int write_flags = job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0;
|
||||
+ int write_flags =
|
||||
+ (job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0) |
|
||||
+ (job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
|
||||
+
|
||||
|
||||
assert(QEMU_IS_ALIGNED(start, job->cluster_size));
|
||||
hbitmap_reset(job->copy_bitmap, start, job->cluster_size);
|
||||
@@ -128,14 +131,8 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- if (buffer_is_zero(*bounce_buffer, nbytes)) {
|
||||
- ret = blk_co_pwrite_zeroes(job->target, start,
|
||||
- nbytes, write_flags | BDRV_REQ_MAY_UNMAP);
|
||||
- } else {
|
||||
- ret = blk_co_pwrite(job->target, start,
|
||||
- nbytes, *bounce_buffer, write_flags |
|
||||
- (job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0));
|
||||
- }
|
||||
+ ret = blk_co_pwrite(job->target, start, nbytes, *bounce_buffer,
|
||||
+ write_flags);
|
||||
if (ret < 0) {
|
||||
trace_backup_do_cow_write_fail(job, start, ret);
|
||||
if (error_is_read) {
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 0a71a15fa2..94e5aee30b 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3572,7 +3572,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
BlockDriverState *source = NULL;
|
||||
BlockJob *job = NULL;
|
||||
AioContext *aio_context;
|
||||
- QDict *options = NULL;
|
||||
+ QDict *options;
|
||||
Error *local_err = NULL;
|
||||
int flags;
|
||||
int64_t size;
|
||||
@@ -3645,10 +3645,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ options = qdict_new();
|
||||
+ qdict_put_str(options, "discard", "unmap");
|
||||
+ qdict_put_str(options, "detect-zeroes", "unmap");
|
||||
if (backup->format) {
|
||||
- if (!options) {
|
||||
- options = qdict_new();
|
||||
- }
|
||||
qdict_put_str(options, "driver", backup->format);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
73
block-backup-hoist-bitmap-check-into-QMP-interface.patch
Normal file
73
block-backup-hoist-bitmap-check-into-QMP-interface.patch
Normal file
@ -0,0 +1,73 @@
|
||||
From 9cc9e9657aad126502183fa4ceb9b962b55471cb Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:55 -0400
|
||||
Subject: [PATCH] block/backup: hoist bitmap check into QMP interface
|
||||
|
||||
This is nicer to do in the unified QMP interface that we have now,
|
||||
because it lets us use the right terminology back at the user.
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190716000117.25219-5-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
block/backup.c | 13 ++++---------
|
||||
blockdev.c | 10 ++++++++++
|
||||
2 files changed, 14 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/block/backup.c b/block/backup.c
|
||||
index 59ac2c0396..cc19643b47 100644
|
||||
--- a/block/backup.c
|
||||
+++ b/block/backup.c
|
||||
@@ -565,6 +565,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
assert(bs);
|
||||
assert(target);
|
||||
|
||||
+ /* QMP interface protects us from these cases */
|
||||
+ assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
|
||||
+ assert(sync_bitmap || sync_mode != MIRROR_SYNC_MODE_BITMAP);
|
||||
+
|
||||
if (bs == target) {
|
||||
error_setg(errp, "Source and target cannot be the same");
|
||||
return NULL;
|
||||
@@ -596,16 +600,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /* QMP interface should have handled translating this to bitmap mode */
|
||||
- assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
|
||||
-
|
||||
if (sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
||||
- if (!sync_bitmap) {
|
||||
- error_setg(errp, "must provide a valid bitmap name for "
|
||||
- "'%s' sync mode", MirrorSyncMode_str(sync_mode));
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
/* If we need to write to this bitmap, check that we can: */
|
||||
if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
|
||||
bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index efb69d343a..0a71a15fa2 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3508,6 +3508,16 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
|
||||
+ (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) {
|
||||
+ /* done before desugaring 'incremental' to print the right message */
|
||||
+ if (!backup->has_bitmap) {
|
||||
+ error_setg(errp, "must provide a valid bitmap name for "
|
||||
+ "'%s' sync mode", MirrorSyncMode_str(backup->sync));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL) {
|
||||
if (backup->has_bitmap_mode &&
|
||||
backup->bitmap_mode != BITMAP_SYNC_MODE_ON_SUCCESS) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
51
block-backup-loosen-restriction-on-readonly-bitmaps.patch
Normal file
51
block-backup-loosen-restriction-on-readonly-bitmaps.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 801e9452bc80a38ee26fe12ba42356851acd6a9e Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:54 -0400
|
||||
Subject: [PATCH] block/backup: loosen restriction on readonly bitmaps
|
||||
|
||||
With the "never" sync policy, we actually can utilize readonly bitmaps
|
||||
now. Loosen the check at the QMP level, and tighten it based on
|
||||
provided arguments down at the job creation level instead.
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190709232550.10724-19-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
block/backup.c | 6 ++++++
|
||||
blockdev.c | 2 +-
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/backup.c b/block/backup.c
|
||||
index 84a56337ac..59ac2c0396 100644
|
||||
--- a/block/backup.c
|
||||
+++ b/block/backup.c
|
||||
@@ -606,6 +606,12 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ /* If we need to write to this bitmap, check that we can: */
|
||||
+ if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
|
||||
+ bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
/* Create a new bitmap, and freeze/disable this one. */
|
||||
if (bdrv_dirty_bitmap_create_successor(bs, sync_bitmap, errp) < 0) {
|
||||
return NULL;
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 34c8b651e1..efb69d343a 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3533,7 +3533,7 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
"when providing a bitmap");
|
||||
return NULL;
|
||||
}
|
||||
- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
+ if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_ALLOW_RO, errp)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
93
blockdev-Return-bs-to-the-proper-context-on-snapshot.patch
Normal file
93
blockdev-Return-bs-to-the-proper-context-on-snapshot.patch
Normal file
@ -0,0 +1,93 @@
|
||||
From dc6b61f12750b3ab5a3965af2ec758750389233d Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Lopez <slp@redhat.com>
|
||||
Date: Wed, 8 Jan 2020 15:31:37 +0100
|
||||
Subject: [PATCH] blockdev: Return bs to the proper context on snapshot abort
|
||||
|
||||
external_snapshot_abort() calls to bdrv_set_backing_hd(), which
|
||||
returns state->old_bs to the main AioContext, as it's intended to be
|
||||
used then the BDS is going to be released. As that's not the case when
|
||||
aborting an external snapshot, return it to the AioContext it was
|
||||
before the call.
|
||||
|
||||
This issue can be triggered by issuing a transaction with two actions,
|
||||
a proper blockdev-snapshot-sync and a bogus one, so the second will
|
||||
trigger a transaction abort. This results in a crash with an stack
|
||||
trace like this one:
|
||||
|
||||
#0 0x00007fa1048b28df in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
|
||||
#1 0x00007fa10489ccf5 in __GI_abort () at abort.c:79
|
||||
#2 0x00007fa10489cbc9 in __assert_fail_base
|
||||
(fmt=0x7fa104a03300 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=0x557224014d30 "block.c", line=2240, function=<optimized out>) at assert.c:92
|
||||
#3 0x00007fa1048aae96 in __GI___assert_fail
|
||||
(assertion=assertion@entry=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=file@entry=0x557224014d30 "block.c", line=line@entry=2240, function=function@entry=0x5572240b5d60 <__PRETTY_FUNCTION__.31620> "bdrv_replace_child_noperm") at assert.c:101
|
||||
#4 0x0000557223e631f8 in bdrv_replace_child_noperm (child=0x557225b9c980, new_bs=new_bs@entry=0x557225c42e40) at block.c:2240
|
||||
#5 0x0000557223e68be7 in bdrv_replace_node (from=0x557226951a60, to=0x557225c42e40, errp=0x5572247d6138 <error_abort>) at block.c:4196
|
||||
#6 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1731
|
||||
#7 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1717
|
||||
#8 0x0000557223d09013 in qmp_transaction (dev_list=<optimized out>, has_props=<optimized out>, props=0x557225cc7d70, errp=errp@entry=0x7ffe704c0c98) at blockdev.c:2360
|
||||
#9 0x0000557223e32085 in qmp_marshal_transaction (args=<optimized out>, ret=<optimized out>, errp=0x7ffe704c0d08) at qapi/qapi-commands-transaction.c:44
|
||||
#10 0x0000557223ee798c in do_qmp_dispatch (errp=0x7ffe704c0d00, allow_oob=<optimized out>, request=<optimized out>, cmds=0x5572247d3cc0 <qmp_commands>) at qapi/qmp-dispatch.c:132
|
||||
#11 0x0000557223ee798c in qmp_dispatch (cmds=0x5572247d3cc0 <qmp_commands>, request=<optimized out>, allow_oob=<optimized out>) at qapi/qmp-dispatch.c:175
|
||||
#12 0x0000557223e06141 in monitor_qmp_dispatch (mon=0x557225c69ff0, req=<optimized out>) at monitor/qmp.c:120
|
||||
#13 0x0000557223e0678a in monitor_qmp_bh_dispatcher (data=<optimized out>) at monitor/qmp.c:209
|
||||
#14 0x0000557223f2f366 in aio_bh_call (bh=0x557225b9dc60) at util/async.c:117
|
||||
#15 0x0000557223f2f366 in aio_bh_poll (ctx=ctx@entry=0x557225b9c840) at util/async.c:117
|
||||
#16 0x0000557223f32754 in aio_dispatch (ctx=0x557225b9c840) at util/aio-posix.c:459
|
||||
#17 0x0000557223f2f242 in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:260
|
||||
#18 0x00007fa10913467d in g_main_dispatch (context=0x557225c28e80) at gmain.c:3176
|
||||
#19 0x00007fa10913467d in g_main_context_dispatch (context=context@entry=0x557225c28e80) at gmain.c:3829
|
||||
#20 0x0000557223f31808 in glib_pollfds_poll () at util/main-loop.c:219
|
||||
#21 0x0000557223f31808 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:242
|
||||
#22 0x0000557223f31808 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:518
|
||||
#23 0x0000557223d13201 in main_loop () at vl.c:1828
|
||||
#24 0x0000557223bbfb82 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4504
|
||||
|
||||
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1779036
|
||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
blockdev.c | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 5088541591..79112be2e6 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -1774,6 +1774,8 @@ static void external_snapshot_abort(BlkActionState *common)
|
||||
if (state->new_bs) {
|
||||
if (state->overlay_appended) {
|
||||
AioContext *aio_context;
|
||||
+ AioContext *tmp_context;
|
||||
+ int ret;
|
||||
|
||||
aio_context = bdrv_get_aio_context(state->old_bs);
|
||||
aio_context_acquire(aio_context);
|
||||
@@ -1781,6 +1783,25 @@ static void external_snapshot_abort(BlkActionState *common)
|
||||
bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd()
|
||||
close state->old_bs; we need it */
|
||||
bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
|
||||
+
|
||||
+ /*
|
||||
+ * The call to bdrv_set_backing_hd() above returns state->old_bs to
|
||||
+ * the main AioContext. As we're still going to be using it, return
|
||||
+ * it to the AioContext it was before.
|
||||
+ */
|
||||
+ tmp_context = bdrv_get_aio_context(state->old_bs);
|
||||
+ if (aio_context != tmp_context) {
|
||||
+ aio_context_release(aio_context);
|
||||
+ aio_context_acquire(tmp_context);
|
||||
+
|
||||
+ ret = bdrv_try_set_aio_context(state->old_bs,
|
||||
+ aio_context, NULL);
|
||||
+ assert(ret == 0);
|
||||
+
|
||||
+ aio_context_release(tmp_context);
|
||||
+ aio_context_acquire(aio_context);
|
||||
+ }
|
||||
+
|
||||
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
|
||||
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
105
blockdev-backup-utilize-do_backup_common.patch
Normal file
105
blockdev-backup-utilize-do_backup_common.patch
Normal file
@ -0,0 +1,105 @@
|
||||
From e5456acf2332efd0ed6106eb13cf24e6bca1ee64 Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:52 -0400
|
||||
Subject: [PATCH] blockdev-backup: utilize do_backup_common
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190709232550.10724-4-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
blockdev.c | 65 +++++-------------------------------------------------
|
||||
1 file changed, 6 insertions(+), 59 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index a29838a1c8..aa15ed1f00 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3668,78 +3668,25 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockDriverState *target_bs;
|
||||
- Error *local_err = NULL;
|
||||
- BdrvDirtyBitmap *bmap = NULL;
|
||||
AioContext *aio_context;
|
||||
- BlockJob *job = NULL;
|
||||
- int job_flags = JOB_DEFAULT;
|
||||
- int ret;
|
||||
-
|
||||
- if (!backup->has_speed) {
|
||||
- backup->speed = 0;
|
||||
- }
|
||||
- if (!backup->has_on_source_error) {
|
||||
- backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||
- }
|
||||
- if (!backup->has_on_target_error) {
|
||||
- backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||
- }
|
||||
- if (!backup->has_job_id) {
|
||||
- backup->job_id = NULL;
|
||||
- }
|
||||
- if (!backup->has_auto_finalize) {
|
||||
- backup->auto_finalize = true;
|
||||
- }
|
||||
- if (!backup->has_auto_dismiss) {
|
||||
- backup->auto_dismiss = true;
|
||||
- }
|
||||
- if (!backup->has_compress) {
|
||||
- backup->compress = false;
|
||||
- }
|
||||
+ BlockJob *job;
|
||||
|
||||
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
||||
if (!bs) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- aio_context = bdrv_get_aio_context(bs);
|
||||
- aio_context_acquire(aio_context);
|
||||
-
|
||||
target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
|
||||
if (!target_bs) {
|
||||
- goto out;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
- if (ret < 0) {
|
||||
- goto out;
|
||||
- }
|
||||
+ aio_context = bdrv_get_aio_context(bs);
|
||||
+ aio_context_acquire(aio_context);
|
||||
|
||||
- if (backup->has_bitmap) {
|
||||
- bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
|
||||
- if (!bmap) {
|
||||
- error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
|
||||
- goto out;
|
||||
- }
|
||||
- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
- goto out;
|
||||
- }
|
||||
- }
|
||||
+ job = do_backup_common(qapi_BlockdevBackup_base(backup),
|
||||
+ bs, target_bs, aio_context, txn, errp);
|
||||
|
||||
- if (!backup->auto_finalize) {
|
||||
- job_flags |= JOB_MANUAL_FINALIZE;
|
||||
- }
|
||||
- if (!backup->auto_dismiss) {
|
||||
- job_flags |= JOB_MANUAL_DISMISS;
|
||||
- }
|
||||
- job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
- backup->sync, bmap, backup->compress,
|
||||
- backup->on_source_error, backup->on_target_error,
|
||||
- job_flags, NULL, NULL, txn, &local_err);
|
||||
- if (local_err != NULL) {
|
||||
- error_propagate(errp, local_err);
|
||||
- }
|
||||
-out:
|
||||
aio_context_release(aio_context);
|
||||
return job;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
44
blockdev-fix-coding-style-issues-in-drive_backup_pre.patch
Normal file
44
blockdev-fix-coding-style-issues-in-drive_backup_pre.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From ffbf1e237d0311512c411e195278e69d710fb9cf Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Lopez <slp@redhat.com>
|
||||
Date: Wed, 8 Jan 2020 15:31:31 +0100
|
||||
Subject: [PATCH] blockdev: fix coding style issues in drive_backup_prepare
|
||||
|
||||
Fix a couple of minor coding style issues in drive_backup_prepare.
|
||||
|
||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
blockdev.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 4435795b6d..99b1cafb8f 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3597,7 +3597,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
|
||||
if (!backup->has_format) {
|
||||
backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
|
||||
- NULL : (char*) bs->drv->format_name;
|
||||
+ NULL : (char *) bs->drv->format_name;
|
||||
}
|
||||
|
||||
/* Early check to avoid creating target */
|
||||
@@ -3607,8 +3607,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
|
||||
flags = bs->open_flags | BDRV_O_RDWR;
|
||||
|
||||
- /* See if we have a backing HD we can use to create our new image
|
||||
- * on top of. */
|
||||
+ /*
|
||||
+ * See if we have a backing HD we can use to create our new image
|
||||
+ * on top of.
|
||||
+ */
|
||||
if (backup->sync == MIRROR_SYNC_MODE_TOP) {
|
||||
source = backing_bs(bs);
|
||||
if (!source) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
191
blockdev-honor-bdrv_try_set_aio_context-context-requ.patch
Normal file
191
blockdev-honor-bdrv_try_set_aio_context-context-requ.patch
Normal file
@ -0,0 +1,191 @@
|
||||
From 64c6b3b911f65c19f3a235c8394f5db894c1ee6a Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Lopez <slp@redhat.com>
|
||||
Date: Wed, 8 Jan 2020 15:31:34 +0100
|
||||
Subject: [PATCH] blockdev: honor bdrv_try_set_aio_context() context
|
||||
requirements
|
||||
|
||||
bdrv_try_set_aio_context() requires that the old context is held, and
|
||||
the new context is not held. Fix all the occurrences where it's not
|
||||
done this way.
|
||||
|
||||
Suggested-by: Max Reitz <mreitz@redhat.com>
|
||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
blockdev.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 60 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index d3309c205a..5088541591 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -1578,6 +1578,7 @@ static void external_snapshot_prepare(BlkActionState *common,
|
||||
DO_UPCAST(ExternalSnapshotState, common, common);
|
||||
TransactionAction *action = common->action;
|
||||
AioContext *aio_context;
|
||||
+ AioContext *old_context;
|
||||
int ret;
|
||||
|
||||
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
|
||||
@@ -1718,7 +1719,16 @@ static void external_snapshot_prepare(BlkActionState *common,
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
||||
+ old_context = bdrv_get_aio_context(state->new_bs);
|
||||
+ aio_context_release(aio_context);
|
||||
+ aio_context_acquire(old_context);
|
||||
+
|
||||
ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
|
||||
+
|
||||
+ aio_context_release(old_context);
|
||||
+ aio_context_acquire(aio_context);
|
||||
+
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -1818,11 +1828,13 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
||||
BlockDriverState *target_bs;
|
||||
BlockDriverState *source = NULL;
|
||||
AioContext *aio_context;
|
||||
+ AioContext *old_context;
|
||||
QDict *options;
|
||||
Error *local_err = NULL;
|
||||
int flags;
|
||||
int64_t size;
|
||||
bool set_backing_hd = false;
|
||||
+ int ret;
|
||||
|
||||
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
||||
backup = common->action->u.drive_backup.data;
|
||||
@@ -1911,6 +1923,21 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
||||
+ old_context = bdrv_get_aio_context(target_bs);
|
||||
+ aio_context_release(aio_context);
|
||||
+ aio_context_acquire(old_context);
|
||||
+
|
||||
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
+ if (ret < 0) {
|
||||
+ bdrv_unref(target_bs);
|
||||
+ aio_context_release(old_context);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ aio_context_release(old_context);
|
||||
+ aio_context_acquire(aio_context);
|
||||
+
|
||||
if (set_backing_hd) {
|
||||
bdrv_set_backing_hd(target_bs, source, &local_err);
|
||||
if (local_err) {
|
||||
@@ -1990,6 +2017,8 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
||||
BlockDriverState *bs;
|
||||
BlockDriverState *target_bs;
|
||||
AioContext *aio_context;
|
||||
+ AioContext *old_context;
|
||||
+ int ret;
|
||||
|
||||
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
||||
backup = common->action->u.blockdev_backup.data;
|
||||
@@ -2004,7 +2033,18 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
+ old_context = bdrv_get_aio_context(target_bs);
|
||||
+ aio_context_acquire(old_context);
|
||||
+
|
||||
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
+ if (ret < 0) {
|
||||
+ aio_context_release(old_context);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ aio_context_release(old_context);
|
||||
aio_context_acquire(aio_context);
|
||||
state->bs = bs;
|
||||
|
||||
@@ -3562,7 +3602,6 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
BlockJob *job = NULL;
|
||||
BdrvDirtyBitmap *bmap = NULL;
|
||||
int job_flags = JOB_DEFAULT;
|
||||
- int ret;
|
||||
|
||||
if (!backup->has_speed) {
|
||||
backup->speed = 0;
|
||||
@@ -3586,11 +3625,6 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
backup->compress = false;
|
||||
}
|
||||
|
||||
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
- if (ret < 0) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
|
||||
(backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) {
|
||||
/* done before desugaring 'incremental' to print the right message */
|
||||
@@ -3802,6 +3836,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
BlockDriverState *bs;
|
||||
BlockDriverState *source, *target_bs;
|
||||
AioContext *aio_context;
|
||||
+ AioContext *old_context;
|
||||
BlockMirrorBackingMode backing_mode;
|
||||
Error *local_err = NULL;
|
||||
QDict *options = NULL;
|
||||
@@ -3914,12 +3949,22 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
(arg->mode == NEW_IMAGE_MODE_EXISTING ||
|
||||
!bdrv_has_zero_init(target_bs)));
|
||||
|
||||
+
|
||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
||||
+ old_context = bdrv_get_aio_context(target_bs);
|
||||
+ aio_context_release(aio_context);
|
||||
+ aio_context_acquire(old_context);
|
||||
+
|
||||
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_unref(target_bs);
|
||||
- goto out;
|
||||
+ aio_context_release(old_context);
|
||||
+ return;
|
||||
}
|
||||
|
||||
+ aio_context_release(old_context);
|
||||
+ aio_context_acquire(aio_context);
|
||||
+
|
||||
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
|
||||
arg->has_replaces, arg->replaces, arg->sync,
|
||||
backing_mode, zero_target,
|
||||
@@ -3961,6 +4006,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
BlockDriverState *bs;
|
||||
BlockDriverState *target_bs;
|
||||
AioContext *aio_context;
|
||||
+ AioContext *old_context;
|
||||
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
|
||||
Error *local_err = NULL;
|
||||
bool zero_target;
|
||||
@@ -3978,10 +4024,16 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
|
||||
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
|
||||
|
||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
||||
+ old_context = bdrv_get_aio_context(target_bs);
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
- aio_context_acquire(aio_context);
|
||||
+ aio_context_acquire(old_context);
|
||||
|
||||
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
+
|
||||
+ aio_context_release(old_context);
|
||||
+ aio_context_acquire(aio_context);
|
||||
+
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
131
blockdev-unify-qmp_blockdev_backup-and-blockdev-back.patch
Normal file
131
blockdev-unify-qmp_blockdev_backup-and-blockdev-back.patch
Normal file
@ -0,0 +1,131 @@
|
||||
From 6d89e4923e9c341975dbfdd2bae153ba367a1b79 Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Lopez <slp@redhat.com>
|
||||
Date: Wed, 8 Jan 2020 15:31:33 +0100
|
||||
Subject: [PATCH] blockdev: unify qmp_blockdev_backup and blockdev-backup
|
||||
transaction paths
|
||||
|
||||
Issuing a blockdev-backup from qmp_blockdev_backup takes a slightly
|
||||
different path than when it's issued from a transaction. In the code,
|
||||
this is manifested as some redundancy between do_blockdev_backup() and
|
||||
blockdev_backup_prepare().
|
||||
|
||||
This change unifies both paths, merging do_blockdev_backup() and
|
||||
blockdev_backup_prepare(), and changing qmp_blockdev_backup() to
|
||||
create a transaction instead of calling do_backup_common() direcly.
|
||||
|
||||
As a side-effect, now qmp_blockdev_backup() is executed inside a
|
||||
drained section, as it happens when creating a blockdev-backup
|
||||
transaction. This change is visible from the user's perspective, as
|
||||
the job gets paused and immediately resumed before starting the actual
|
||||
work.
|
||||
|
||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
blockdev.c | 60 ++++++++++++------------------------------------------
|
||||
1 file changed, 13 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 7016054688..d3309c205a 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -1983,16 +1983,13 @@ typedef struct BlockdevBackupState {
|
||||
BlockJob *job;
|
||||
} BlockdevBackupState;
|
||||
|
||||
-static BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
|
||||
- Error **errp);
|
||||
-
|
||||
static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
||||
{
|
||||
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
|
||||
BlockdevBackup *backup;
|
||||
- BlockDriverState *bs, *target;
|
||||
+ BlockDriverState *bs;
|
||||
+ BlockDriverState *target_bs;
|
||||
AioContext *aio_context;
|
||||
- Error *local_err = NULL;
|
||||
|
||||
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
||||
backup = common->action->u.blockdev_backup.data;
|
||||
@@ -2002,8 +1999,8 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
- target = bdrv_lookup_bs(backup->target, backup->target, errp);
|
||||
- if (!target) {
|
||||
+ target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
|
||||
+ if (!target_bs) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2014,13 +2011,10 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
||||
/* Paired with .clean() */
|
||||
bdrv_drained_begin(state->bs);
|
||||
|
||||
- state->job = do_blockdev_backup(backup, common->block_job_txn, &local_err);
|
||||
- if (local_err) {
|
||||
- error_propagate(errp, local_err);
|
||||
- goto out;
|
||||
- }
|
||||
+ state->job = do_backup_common(qapi_BlockdevBackup_base(backup),
|
||||
+ bs, target_bs, aio_context,
|
||||
+ common->block_job_txn, errp);
|
||||
|
||||
-out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
@@ -3672,41 +3666,13 @@ XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp)
|
||||
return bdrv_get_xdbg_block_graph(errp);
|
||||
}
|
||||
|
||||
-BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
|
||||
- Error **errp)
|
||||
+void qmp_blockdev_backup(BlockdevBackup *backup, Error **errp)
|
||||
{
|
||||
- BlockDriverState *bs;
|
||||
- BlockDriverState *target_bs;
|
||||
- AioContext *aio_context;
|
||||
- BlockJob *job;
|
||||
-
|
||||
- bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
||||
- if (!bs) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
|
||||
- if (!target_bs) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- aio_context = bdrv_get_aio_context(bs);
|
||||
- aio_context_acquire(aio_context);
|
||||
-
|
||||
- job = do_backup_common(qapi_BlockdevBackup_base(backup),
|
||||
- bs, target_bs, aio_context, txn, errp);
|
||||
-
|
||||
- aio_context_release(aio_context);
|
||||
- return job;
|
||||
-}
|
||||
-
|
||||
-void qmp_blockdev_backup(BlockdevBackup *arg, Error **errp)
|
||||
-{
|
||||
- BlockJob *job;
|
||||
- job = do_blockdev_backup(arg, NULL, errp);
|
||||
- if (job) {
|
||||
- job_start(&job->job);
|
||||
- }
|
||||
+ TransactionAction action = {
|
||||
+ .type = TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP,
|
||||
+ .u.blockdev_backup.data = backup,
|
||||
+ };
|
||||
+ blockdev_do_action(&action, errp);
|
||||
}
|
||||
|
||||
/* Parameter check and block job starting for drive mirroring.
|
||||
--
|
||||
2.27.0
|
||||
|
||||
406
blockdev-unify-qmp_drive_backup-and-drive-backup-tra.patch
Normal file
406
blockdev-unify-qmp_drive_backup-and-drive-backup-tra.patch
Normal file
@ -0,0 +1,406 @@
|
||||
From 952f7f53cdd4320d1a0328481fa578dd199eb1ce Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Lopez <slp@redhat.com>
|
||||
Date: Wed, 8 Jan 2020 15:31:32 +0100
|
||||
Subject: [PATCH] blockdev: unify qmp_drive_backup and drive-backup transaction
|
||||
paths
|
||||
|
||||
Issuing a drive-backup from qmp_drive_backup takes a slightly
|
||||
different path than when it's issued from a transaction. In the code,
|
||||
this is manifested as some redundancy between do_drive_backup() and
|
||||
drive_backup_prepare().
|
||||
|
||||
This change unifies both paths, merging do_drive_backup() and
|
||||
drive_backup_prepare(), and changing qmp_drive_backup() to create a
|
||||
transaction instead of calling do_backup_common() direcly.
|
||||
|
||||
As a side-effect, now qmp_drive_backup() is executed inside a drained
|
||||
section, as it happens when creating a drive-backup transaction. This
|
||||
change is visible from the user's perspective, as the job gets paused
|
||||
and immediately resumed before starting the actual work.
|
||||
|
||||
Also fix tests 141, 185 and 219 to cope with the extra
|
||||
JOB_STATUS_CHANGE lines.
|
||||
|
||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
blockdev.c | 224 +++++++++++++++++--------------------
|
||||
tests/qemu-iotests/141.out | 2 +
|
||||
tests/qemu-iotests/185.out | 2 +
|
||||
tests/qemu-iotests/219 | 7 +-
|
||||
tests/qemu-iotests/219.out | 8 ++
|
||||
5 files changed, 117 insertions(+), 126 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 99b1cafb8f..7016054688 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -1804,39 +1804,128 @@ typedef struct DriveBackupState {
|
||||
BlockJob *job;
|
||||
} DriveBackupState;
|
||||
|
||||
-static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
- Error **errp);
|
||||
+static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
+ BlockDriverState *bs,
|
||||
+ BlockDriverState *target_bs,
|
||||
+ AioContext *aio_context,
|
||||
+ JobTxn *txn, Error **errp);
|
||||
|
||||
static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
||||
{
|
||||
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
|
||||
- BlockDriverState *bs;
|
||||
DriveBackup *backup;
|
||||
+ BlockDriverState *bs;
|
||||
+ BlockDriverState *target_bs;
|
||||
+ BlockDriverState *source = NULL;
|
||||
AioContext *aio_context;
|
||||
+ QDict *options;
|
||||
Error *local_err = NULL;
|
||||
+ int flags;
|
||||
+ int64_t size;
|
||||
+ bool set_backing_hd = false;
|
||||
|
||||
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
||||
backup = common->action->u.drive_backup.data;
|
||||
|
||||
+ if (!backup->has_mode) {
|
||||
+ backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
+ }
|
||||
+
|
||||
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
||||
if (!bs) {
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (!bs->drv) {
|
||||
+ error_setg(errp, "Device has no medium");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
/* Paired with .clean() */
|
||||
bdrv_drained_begin(bs);
|
||||
|
||||
- state->bs = bs;
|
||||
+ if (!backup->has_format) {
|
||||
+ backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
|
||||
+ NULL : (char *) bs->drv->format_name;
|
||||
+ }
|
||||
+
|
||||
+ /* Early check to avoid creating target */
|
||||
+ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ flags = bs->open_flags | BDRV_O_RDWR;
|
||||
+
|
||||
+ /*
|
||||
+ * See if we have a backing HD we can use to create our new image
|
||||
+ * on top of.
|
||||
+ */
|
||||
+ if (backup->sync == MIRROR_SYNC_MODE_TOP) {
|
||||
+ source = backing_bs(bs);
|
||||
+ if (!source) {
|
||||
+ backup->sync = MIRROR_SYNC_MODE_FULL;
|
||||
+ }
|
||||
+ }
|
||||
+ if (backup->sync == MIRROR_SYNC_MODE_NONE) {
|
||||
+ source = bs;
|
||||
+ flags |= BDRV_O_NO_BACKING;
|
||||
+ set_backing_hd = true;
|
||||
+ }
|
||||
+
|
||||
+ size = bdrv_getlength(bs);
|
||||
+ if (size < 0) {
|
||||
+ error_setg_errno(errp, -size, "bdrv_getlength failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
|
||||
+ assert(backup->format);
|
||||
+ if (source) {
|
||||
+ bdrv_refresh_filename(source);
|
||||
+ bdrv_img_create(backup->target, backup->format, source->filename,
|
||||
+ source->drv->format_name, NULL,
|
||||
+ size, flags, false, &local_err);
|
||||
+ } else {
|
||||
+ bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
|
||||
+ size, flags, false, &local_err);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- state->job = do_drive_backup(backup, common->block_job_txn, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ options = qdict_new();
|
||||
+ qdict_put_str(options, "discard", "unmap");
|
||||
+ qdict_put_str(options, "detect-zeroes", "unmap");
|
||||
+ if (backup->format) {
|
||||
+ qdict_put_str(options, "driver", backup->format);
|
||||
+ }
|
||||
+
|
||||
+ target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
|
||||
+ if (!target_bs) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (set_backing_hd) {
|
||||
+ bdrv_set_backing_hd(target_bs, source, &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto unref;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ state->bs = bs;
|
||||
+
|
||||
+ state->job = do_backup_common(qapi_DriveBackup_base(backup),
|
||||
+ bs, target_bs, aio_context,
|
||||
+ common->block_job_txn, errp);
|
||||
+
|
||||
+unref:
|
||||
+ bdrv_unref(target_bs);
|
||||
out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
@@ -3564,126 +3653,13 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
return job;
|
||||
}
|
||||
|
||||
-static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
- Error **errp)
|
||||
-{
|
||||
- BlockDriverState *bs;
|
||||
- BlockDriverState *target_bs;
|
||||
- BlockDriverState *source = NULL;
|
||||
- BlockJob *job = NULL;
|
||||
- AioContext *aio_context;
|
||||
- QDict *options;
|
||||
- Error *local_err = NULL;
|
||||
- int flags;
|
||||
- int64_t size;
|
||||
- bool set_backing_hd = false;
|
||||
-
|
||||
- if (!backup->has_mode) {
|
||||
- backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
- }
|
||||
-
|
||||
- bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
||||
- if (!bs) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- if (!bs->drv) {
|
||||
- error_setg(errp, "Device has no medium");
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- aio_context = bdrv_get_aio_context(bs);
|
||||
- aio_context_acquire(aio_context);
|
||||
-
|
||||
- if (!backup->has_format) {
|
||||
- backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
|
||||
- NULL : (char *) bs->drv->format_name;
|
||||
- }
|
||||
-
|
||||
- /* Early check to avoid creating target */
|
||||
- if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- flags = bs->open_flags | BDRV_O_RDWR;
|
||||
-
|
||||
- /*
|
||||
- * See if we have a backing HD we can use to create our new image
|
||||
- * on top of.
|
||||
- */
|
||||
- if (backup->sync == MIRROR_SYNC_MODE_TOP) {
|
||||
- source = backing_bs(bs);
|
||||
- if (!source) {
|
||||
- backup->sync = MIRROR_SYNC_MODE_FULL;
|
||||
- }
|
||||
- }
|
||||
- if (backup->sync == MIRROR_SYNC_MODE_NONE) {
|
||||
- source = bs;
|
||||
- flags |= BDRV_O_NO_BACKING;
|
||||
- set_backing_hd = true;
|
||||
- }
|
||||
-
|
||||
- size = bdrv_getlength(bs);
|
||||
- if (size < 0) {
|
||||
- error_setg_errno(errp, -size, "bdrv_getlength failed");
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
|
||||
- assert(backup->format);
|
||||
- if (source) {
|
||||
- bdrv_refresh_filename(source);
|
||||
- bdrv_img_create(backup->target, backup->format, source->filename,
|
||||
- source->drv->format_name, NULL,
|
||||
- size, flags, false, &local_err);
|
||||
- } else {
|
||||
- bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
|
||||
- size, flags, false, &local_err);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (local_err) {
|
||||
- error_propagate(errp, local_err);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- options = qdict_new();
|
||||
- qdict_put_str(options, "discard", "unmap");
|
||||
- qdict_put_str(options, "detect-zeroes", "unmap");
|
||||
- if (backup->format) {
|
||||
- qdict_put_str(options, "driver", backup->format);
|
||||
- }
|
||||
-
|
||||
- target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
|
||||
- if (!target_bs) {
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (set_backing_hd) {
|
||||
- bdrv_set_backing_hd(target_bs, source, &local_err);
|
||||
- if (local_err) {
|
||||
- goto unref;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- job = do_backup_common(qapi_DriveBackup_base(backup),
|
||||
- bs, target_bs, aio_context, txn, errp);
|
||||
-
|
||||
-unref:
|
||||
- bdrv_unref(target_bs);
|
||||
-out:
|
||||
- aio_context_release(aio_context);
|
||||
- return job;
|
||||
-}
|
||||
-
|
||||
-void qmp_drive_backup(DriveBackup *arg, Error **errp)
|
||||
+void qmp_drive_backup(DriveBackup *backup, Error **errp)
|
||||
{
|
||||
-
|
||||
- BlockJob *job;
|
||||
- job = do_drive_backup(arg, NULL, errp);
|
||||
- if (job) {
|
||||
- job_start(&job->job);
|
||||
- }
|
||||
+ TransactionAction action = {
|
||||
+ .type = TRANSACTION_ACTION_KIND_DRIVE_BACKUP,
|
||||
+ .u.drive_backup.data = backup,
|
||||
+ };
|
||||
+ blockdev_do_action(&action, errp);
|
||||
}
|
||||
|
||||
BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
|
||||
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
|
||||
index 4d71d9dcae..07e0ec66d7 100644
|
||||
--- a/tests/qemu-iotests/141.out
|
||||
+++ b/tests/qemu-iotests/141.out
|
||||
@@ -10,6 +10,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
|
||||
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
|
||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
|
||||
{"return": {}}
|
||||
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
|
||||
index ddfbf3c765..a233be7f58 100644
|
||||
--- a/tests/qemu-iotests/185.out
|
||||
+++ b/tests/qemu-iotests/185.out
|
||||
@@ -51,6 +51,8 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l
|
||||
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
|
||||
index e0c51662c0..655f54d881 100755
|
||||
--- a/tests/qemu-iotests/219
|
||||
+++ b/tests/qemu-iotests/219
|
||||
@@ -63,7 +63,7 @@ def test_pause_resume(vm):
|
||||
# logged immediately
|
||||
iotests.log(vm.qmp('query-jobs'))
|
||||
|
||||
-def test_job_lifecycle(vm, job, job_args, has_ready=False):
|
||||
+def test_job_lifecycle(vm, job, job_args, has_ready=False, is_mirror=False):
|
||||
global img_size
|
||||
|
||||
iotests.log('')
|
||||
@@ -135,6 +135,9 @@ def test_job_lifecycle(vm, job, job_args, has_ready=False):
|
||||
iotests.log('Waiting for PENDING state...')
|
||||
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
||||
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
||||
+ if is_mirror:
|
||||
+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
||||
+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
||||
|
||||
if not job_args.get('auto-finalize', True):
|
||||
# PENDING state:
|
||||
@@ -218,7 +221,7 @@ with iotests.FilePath('disk.img') as disk_path, \
|
||||
|
||||
for auto_finalize in [True, False]:
|
||||
for auto_dismiss in [True, False]:
|
||||
- test_job_lifecycle(vm, 'drive-backup', job_args={
|
||||
+ test_job_lifecycle(vm, 'drive-backup', is_mirror=True, job_args={
|
||||
'device': 'drive0-node',
|
||||
'target': copy_path,
|
||||
'sync': 'full',
|
||||
diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out
|
||||
index 8ebd3fee60..0ea5d0b9d5 100644
|
||||
--- a/tests/qemu-iotests/219.out
|
||||
+++ b/tests/qemu-iotests/219.out
|
||||
@@ -135,6 +135,8 @@ Pause/resume in RUNNING
|
||||
{"return": {}}
|
||||
|
||||
Waiting for PENDING state...
|
||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
@@ -186,6 +188,8 @@ Pause/resume in RUNNING
|
||||
{"return": {}}
|
||||
|
||||
Waiting for PENDING state...
|
||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
@@ -245,6 +249,8 @@ Pause/resume in RUNNING
|
||||
{"return": {}}
|
||||
|
||||
Waiting for PENDING state...
|
||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]}
|
||||
@@ -304,6 +310,8 @@ Pause/resume in RUNNING
|
||||
{"return": {}}
|
||||
|
||||
Waiting for PENDING state...
|
||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
163
drive-backup-create-do_backup_common.patch
Normal file
163
drive-backup-create-do_backup_common.patch
Normal file
@ -0,0 +1,163 @@
|
||||
From 98dcfbd5ee53f3be705df7acf37e8706533f494f Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:52 -0400
|
||||
Subject: [PATCH] drive-backup: create do_backup_common
|
||||
|
||||
Create a common core that comprises the actual meat of what the backup API
|
||||
boundary needs to do, and then switch drive-backup to use it.
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190709232550.10724-3-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
blockdev.c | 102 ++++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 57 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 99c92b96d2..a29838a1c8 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3469,20 +3469,16 @@ out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
-static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
- Error **errp)
|
||||
+/* Common QMP interface for drive-backup and blockdev-backup */
|
||||
+static BlockJob *do_backup_common(BackupCommon *backup,
|
||||
+ BlockDriverState *bs,
|
||||
+ BlockDriverState *target_bs,
|
||||
+ AioContext *aio_context,
|
||||
+ JobTxn *txn, Error **errp)
|
||||
{
|
||||
- BlockDriverState *bs;
|
||||
- BlockDriverState *target_bs;
|
||||
- BlockDriverState *source = NULL;
|
||||
BlockJob *job = NULL;
|
||||
BdrvDirtyBitmap *bmap = NULL;
|
||||
- AioContext *aio_context;
|
||||
- QDict *options = NULL;
|
||||
- Error *local_err = NULL;
|
||||
- int flags, job_flags = JOB_DEFAULT;
|
||||
- int64_t size;
|
||||
- bool set_backing_hd = false;
|
||||
+ int job_flags = JOB_DEFAULT;
|
||||
int ret;
|
||||
|
||||
if (!backup->has_speed) {
|
||||
@@ -3494,9 +3490,6 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
if (!backup->has_on_target_error) {
|
||||
backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||
}
|
||||
- if (!backup->has_mode) {
|
||||
- backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
- }
|
||||
if (!backup->has_job_id) {
|
||||
backup->job_id = NULL;
|
||||
}
|
||||
@@ -3510,6 +3503,54 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
backup->compress = false;
|
||||
}
|
||||
|
||||
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
+ if (ret < 0) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (backup->has_bitmap) {
|
||||
+ bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
|
||||
+ if (!bmap) {
|
||||
+ error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!backup->auto_finalize) {
|
||||
+ job_flags |= JOB_MANUAL_FINALIZE;
|
||||
+ }
|
||||
+ if (!backup->auto_dismiss) {
|
||||
+ job_flags |= JOB_MANUAL_DISMISS;
|
||||
+ }
|
||||
+
|
||||
+ job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
+ backup->sync, bmap, backup->compress,
|
||||
+ backup->on_source_error, backup->on_target_error,
|
||||
+ job_flags, NULL, NULL, txn, errp);
|
||||
+ return job;
|
||||
+}
|
||||
+
|
||||
+static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ BlockDriverState *bs;
|
||||
+ BlockDriverState *target_bs;
|
||||
+ BlockDriverState *source = NULL;
|
||||
+ BlockJob *job = NULL;
|
||||
+ AioContext *aio_context;
|
||||
+ QDict *options = NULL;
|
||||
+ Error *local_err = NULL;
|
||||
+ int flags;
|
||||
+ int64_t size;
|
||||
+ bool set_backing_hd = false;
|
||||
+
|
||||
+ if (!backup->has_mode) {
|
||||
+ backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
+ }
|
||||
+
|
||||
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
||||
if (!bs) {
|
||||
return NULL;
|
||||
@@ -3585,12 +3626,6 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
- if (ret < 0) {
|
||||
- bdrv_unref(target_bs);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
if (set_backing_hd) {
|
||||
bdrv_set_backing_hd(target_bs, source, &local_err);
|
||||
if (local_err) {
|
||||
@@ -3598,31 +3633,8 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
||||
}
|
||||
}
|
||||
|
||||
- if (backup->has_bitmap) {
|
||||
- bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
|
||||
- if (!bmap) {
|
||||
- error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
|
||||
- goto unref;
|
||||
- }
|
||||
- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
- goto unref;
|
||||
- }
|
||||
- }
|
||||
- if (!backup->auto_finalize) {
|
||||
- job_flags |= JOB_MANUAL_FINALIZE;
|
||||
- }
|
||||
- if (!backup->auto_dismiss) {
|
||||
- job_flags |= JOB_MANUAL_DISMISS;
|
||||
- }
|
||||
-
|
||||
- job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
- backup->sync, bmap, backup->compress,
|
||||
- backup->on_source_error, backup->on_target_error,
|
||||
- job_flags, NULL, NULL, txn, &local_err);
|
||||
- if (local_err != NULL) {
|
||||
- error_propagate(errp, local_err);
|
||||
- goto unref;
|
||||
- }
|
||||
+ job = do_backup_common(qapi_DriveBackup_base(backup),
|
||||
+ bs, target_bs, aio_context, txn, errp);
|
||||
|
||||
unref:
|
||||
bdrv_unref(target_bs);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
68
hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch
Normal file
68
hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 86f70ed090478cc3b569b3606eb2723a0baadb52 Mon Sep 17 00:00:00 2001
|
||||
From: Julia Suvorova <jusual@redhat.com>
|
||||
Date: Tue, 16 Jun 2020 12:25:36 -0400
|
||||
Subject: [PATCH] hw/pci/pcie: Move hot plug capability check to pre_plug
|
||||
callback
|
||||
|
||||
RH-Author: Julia Suvorova <jusual@redhat.com>
|
||||
Message-id: <20200616122536.1027685-1-jusual@redhat.com>
|
||||
Patchwork-id: 97548
|
||||
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/1] hw/pci/pcie: Move hot plug capability check to pre_plug callback
|
||||
Bugzilla: 1820531
|
||||
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
|
||||
RH-Acked-by: Auger Eric <eric.auger@redhat.com>
|
||||
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
|
||||
|
||||
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1820531
|
||||
BRANCH: rhel-av-8.2.1
|
||||
UPSTREAM: merged
|
||||
BREW: 29422092
|
||||
|
||||
Check for hot plug capability earlier to avoid removing devices attached
|
||||
during the initialization process.
|
||||
|
||||
Run qemu with an unattached drive:
|
||||
-drive file=$FILE,if=none,id=drive0 \
|
||||
-device pcie-root-port,id=rp0,slot=3,bus=pcie.0,hotplug=off
|
||||
Hotplug a block device:
|
||||
device_add virtio-blk-pci,id=blk0,drive=drive0,bus=rp0
|
||||
If hotplug fails on plug_cb, drive0 will be deleted.
|
||||
|
||||
Fixes: 0501e1aa1d32a6 ("hw/pci/pcie: Forbid hot-plug if it's disabled on the slot")
|
||||
|
||||
Acked-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Signed-off-by: Julia Suvorova <jusual@redhat.com>
|
||||
Message-Id: <20200604125947.881210-1-jusual@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry picked from commit 0dabc0f6544f2c0310546f6d6cf3b68979580a9c)
|
||||
Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
|
||||
---
|
||||
hw/pci/pcie.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
|
||||
index 2b4eedd2bb..b5190a3a55 100644
|
||||
--- a/hw/pci/pcie.c
|
||||
+++ b/hw/pci/pcie.c
|
||||
@@ -419,6 +419,17 @@ static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev,
|
||||
void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
{
|
||||
+ PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
|
||||
+ uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
|
||||
+ uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP);
|
||||
+
|
||||
+ /* Check if hot-plug is disabled on the slot */
|
||||
+ if (dev->hotplugged && (sltcap & PCI_EXP_SLTCAP_HPC) == 0) {
|
||||
+ error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'",
|
||||
+ DEVICE(hotplug_pdev)->id);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
173
migration-Rate-limit-inside-host-pages.patch
Normal file
173
migration-Rate-limit-inside-host-pages.patch
Normal file
@ -0,0 +1,173 @@
|
||||
From 3e8a587b055f0e3cabf91921fca0777fe7e349f5 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Vivier <lvivier@redhat.com>
|
||||
Date: Tue, 17 Mar 2020 17:05:18 +0000
|
||||
Subject: [PATCH] migration: Rate limit inside host pages
|
||||
|
||||
RH-Author: Laurent Vivier <lvivier@redhat.com>
|
||||
Message-id: <20200317170518.9303-1-lvivier@redhat.com>
|
||||
Patchwork-id: 94374
|
||||
O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH] migration: Rate limit inside host pages
|
||||
Bugzilla: 1814336
|
||||
RH-Acked-by: Peter Xu <peterx@redhat.com>
|
||||
RH-Acked-by: Juan Quintela <quintela@redhat.com>
|
||||
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
|
||||
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
|
||||
|
||||
When using hugepages, rate limiting is necessary within each huge
|
||||
page, since a 1G huge page can take a significant time to send, so
|
||||
you end up with bursty behaviour.
|
||||
|
||||
Fixes: 4c011c37ecb3 ("postcopy: Send whole huge pages")
|
||||
Reported-by: Lin Ma <LMa@suse.com>
|
||||
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Reviewed-by: Juan Quintela <quintela@redhat.com>
|
||||
Reviewed-by: Peter Xu <peterx@redhat.com>
|
||||
Signed-off-by: Juan Quintela <quintela@redhat.com>
|
||||
(cherry picked from commit 97e1e06780e70f6e98a0d2df881e0c0927d3aeb6)
|
||||
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
|
||||
|
||||
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1814336
|
||||
BRANCH: rhel-av-8.2.0
|
||||
UPSTREAM: Merged
|
||||
BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=27283241
|
||||
TESTED: Tested that the migration abort doesn't trigger an error message in
|
||||
the kernel logs on P9
|
||||
|
||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||
---
|
||||
migration/migration.c | 57 ++++++++++++++++++++++++------------------
|
||||
migration/migration.h | 1 +
|
||||
migration/ram.c | 2 ++
|
||||
migration/trace-events | 4 +--
|
||||
4 files changed, 37 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/migration/migration.c b/migration/migration.c
|
||||
index fd7d81d4b6..b0b9430822 100644
|
||||
--- a/migration/migration.c
|
||||
+++ b/migration/migration.c
|
||||
@@ -3260,6 +3260,37 @@ void migration_consume_urgent_request(void)
|
||||
qemu_sem_wait(&migrate_get_current()->rate_limit_sem);
|
||||
}
|
||||
|
||||
+/* Returns true if the rate limiting was broken by an urgent request */
|
||||
+bool migration_rate_limit(void)
|
||||
+{
|
||||
+ int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||
+ MigrationState *s = migrate_get_current();
|
||||
+
|
||||
+ bool urgent = false;
|
||||
+ migration_update_counters(s, now);
|
||||
+ if (qemu_file_rate_limit(s->to_dst_file)) {
|
||||
+ /*
|
||||
+ * Wait for a delay to do rate limiting OR
|
||||
+ * something urgent to post the semaphore.
|
||||
+ */
|
||||
+ int ms = s->iteration_start_time + BUFFER_DELAY - now;
|
||||
+ trace_migration_rate_limit_pre(ms);
|
||||
+ if (qemu_sem_timedwait(&s->rate_limit_sem, ms) == 0) {
|
||||
+ /*
|
||||
+ * We were woken by one or more urgent things but
|
||||
+ * the timedwait will have consumed one of them.
|
||||
+ * The service routine for the urgent wake will dec
|
||||
+ * the semaphore itself for each item it consumes,
|
||||
+ * so add this one we just eat back.
|
||||
+ */
|
||||
+ qemu_sem_post(&s->rate_limit_sem);
|
||||
+ urgent = true;
|
||||
+ }
|
||||
+ trace_migration_rate_limit_post(urgent);
|
||||
+ }
|
||||
+ return urgent;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Master migration thread on the source VM.
|
||||
* It drives the migration and pumps the data down the outgoing channel.
|
||||
@@ -3313,8 +3344,6 @@ static void *migration_thread(void *opaque)
|
||||
trace_migration_thread_setup_complete();
|
||||
|
||||
while (migration_is_active(s)) {
|
||||
- int64_t current_time;
|
||||
-
|
||||
if (urgent || !qemu_file_rate_limit(s->to_dst_file)) {
|
||||
MigIterateState iter_state = migration_iteration_run(s);
|
||||
if (iter_state == MIG_ITERATE_SKIP) {
|
||||
@@ -3341,29 +3370,7 @@ static void *migration_thread(void *opaque)
|
||||
update_iteration_initial_status(s);
|
||||
}
|
||||
|
||||
- current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||
-
|
||||
- migration_update_counters(s, current_time);
|
||||
-
|
||||
- urgent = false;
|
||||
- if (qemu_file_rate_limit(s->to_dst_file)) {
|
||||
- /* Wait for a delay to do rate limiting OR
|
||||
- * something urgent to post the semaphore.
|
||||
- */
|
||||
- int ms = s->iteration_start_time + BUFFER_DELAY - current_time;
|
||||
- trace_migration_thread_ratelimit_pre(ms);
|
||||
- if (qemu_sem_timedwait(&s->rate_limit_sem, ms) == 0) {
|
||||
- /* We were worken by one or more urgent things but
|
||||
- * the timedwait will have consumed one of them.
|
||||
- * The service routine for the urgent wake will dec
|
||||
- * the semaphore itself for each item it consumes,
|
||||
- * so add this one we just eat back.
|
||||
- */
|
||||
- qemu_sem_post(&s->rate_limit_sem);
|
||||
- urgent = true;
|
||||
- }
|
||||
- trace_migration_thread_ratelimit_post(urgent);
|
||||
- }
|
||||
+ urgent = migration_rate_limit();
|
||||
}
|
||||
|
||||
trace_migration_thread_after_loop();
|
||||
diff --git a/migration/migration.h b/migration/migration.h
|
||||
index 4aa72297fc..ff8a0bf12d 100644
|
||||
--- a/migration/migration.h
|
||||
+++ b/migration/migration.h
|
||||
@@ -345,6 +345,7 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque);
|
||||
|
||||
void migration_make_urgent_request(void);
|
||||
void migration_consume_urgent_request(void);
|
||||
+bool migration_rate_limit(void);
|
||||
|
||||
int migration_send_initial_packet(QIOChannel *c, uint8_t id, Error **errp);
|
||||
int migration_recv_initial_packet(QIOChannel *c, Error **errp);
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index 27585a4f3e..d6657a8093 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -3076,6 +3076,8 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss,
|
||||
}
|
||||
|
||||
pss->page++;
|
||||
+ /* Allow rate limiting to happen in the middle of huge pages */
|
||||
+ migration_rate_limit();
|
||||
} while ((pss->page & (pagesize_bits - 1)) &&
|
||||
offset_in_ramblock(pss->block, pss->page << TARGET_PAGE_BITS));
|
||||
|
||||
diff --git a/migration/trace-events b/migration/trace-events
|
||||
index c0640cd424..b4d85229d9 100644
|
||||
--- a/migration/trace-events
|
||||
+++ b/migration/trace-events
|
||||
@@ -131,12 +131,12 @@ migrate_send_rp_recv_bitmap(char *name, int64_t size) "block '%s' size 0x%"PRIi6
|
||||
migration_completion_file_err(void) ""
|
||||
migration_completion_postcopy_end(void) ""
|
||||
migration_completion_postcopy_end_after_complete(void) ""
|
||||
+migration_rate_limit_pre(int ms) "%d ms"
|
||||
+migration_rate_limit_post(int urgent) "urgent: %d"
|
||||
migration_return_path_end_before(void) ""
|
||||
migration_return_path_end_after(int rp_error) "%d"
|
||||
migration_thread_after_loop(void) ""
|
||||
migration_thread_file_err(void) ""
|
||||
-migration_thread_ratelimit_pre(int ms) "%d ms"
|
||||
-migration_thread_ratelimit_post(int urgent) "urgent: %d"
|
||||
migration_thread_setup_complete(void) ""
|
||||
open_return_path_on_source(void) ""
|
||||
open_return_path_on_source_continue(void) ""
|
||||
--
|
||||
2.27.0
|
||||
|
||||
68
migration-use-migration_is_active-to-represent-activ.patch
Normal file
68
migration-use-migration_is_active-to-represent-activ.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 9662d44633dd4582dc47d58f63ee63b2c8f60a4f Mon Sep 17 00:00:00 2001
|
||||
From: Wei Yang <richardw.yang@linux.intel.com>
|
||||
Date: Wed, 17 Jul 2019 08:53:41 +0800
|
||||
Subject: [PATCH] migration: use migration_is_active to represent active state
|
||||
|
||||
Wrap the check into a function to make it easy to read.
|
||||
|
||||
Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
|
||||
Message-Id: <20190717005341.14140-1-richardw.yang@linux.intel.com>
|
||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
---
|
||||
include/migration/misc.h | 1 +
|
||||
migration/migration.c | 12 ++++++++----
|
||||
2 files changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/include/migration/misc.h b/include/migration/misc.h
|
||||
index 5cdbabd094..42d6abc920 100644
|
||||
--- a/include/migration/misc.h
|
||||
+++ b/include/migration/misc.h
|
||||
@@ -61,6 +61,7 @@ void migration_object_init(void);
|
||||
void migration_shutdown(void);
|
||||
void qemu_start_incoming_migration(const char *uri, Error **errp);
|
||||
bool migration_is_idle(void);
|
||||
+bool migration_is_active(MigrationState *);
|
||||
void add_migration_state_change_notifier(Notifier *notify);
|
||||
void remove_migration_state_change_notifier(Notifier *notify);
|
||||
bool migration_in_setup(MigrationState *);
|
||||
diff --git a/migration/migration.c b/migration/migration.c
|
||||
index 9b40380d7c..fd7d81d4b6 100644
|
||||
--- a/migration/migration.c
|
||||
+++ b/migration/migration.c
|
||||
@@ -1578,8 +1578,7 @@ static void migrate_fd_cleanup(MigrationState *s)
|
||||
qemu_fclose(tmp);
|
||||
}
|
||||
|
||||
- assert((s->state != MIGRATION_STATUS_ACTIVE) &&
|
||||
- (s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE));
|
||||
+ assert(!migration_is_active(s));
|
||||
|
||||
if (s->state == MIGRATION_STATUS_CANCELLING) {
|
||||
migrate_set_state(&s->state, MIGRATION_STATUS_CANCELLING,
|
||||
@@ -1741,6 +1740,12 @@ bool migration_is_idle(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
+bool migration_is_active(MigrationState *s)
|
||||
+{
|
||||
+ return (s->state == MIGRATION_STATUS_ACTIVE ||
|
||||
+ s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE);
|
||||
+}
|
||||
+
|
||||
void migrate_init(MigrationState *s)
|
||||
{
|
||||
/*
|
||||
@@ -3307,8 +3312,7 @@ static void *migration_thread(void *opaque)
|
||||
|
||||
trace_migration_thread_setup_complete();
|
||||
|
||||
- while (s->state == MIGRATION_STATUS_ACTIVE ||
|
||||
- s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
|
||||
+ while (migration_is_active(s)) {
|
||||
int64_t current_time;
|
||||
|
||||
if (urgent || !qemu_file_rate_limit(s->to_dst_file)) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
205
mirror-Fix-bdrv_has_zero_init-use.patch
Normal file
205
mirror-Fix-bdrv_has_zero_init-use.patch
Normal file
@ -0,0 +1,205 @@
|
||||
From 7fcb1c1a956a8cad5c2e8585e53878edc4fd9eca Mon Sep 17 00:00:00 2001
|
||||
From: Max Reitz <mreitz@redhat.com>
|
||||
Date: Wed, 24 Jul 2019 19:12:30 +0200
|
||||
Subject: [PATCH] mirror: Fix bdrv_has_zero_init() use
|
||||
|
||||
bdrv_has_zero_init() only has meaning for newly created images or image
|
||||
areas. If the mirror job itself did not create the image, it cannot
|
||||
rely on bdrv_has_zero_init()'s result to carry any meaning.
|
||||
|
||||
This is the case for drive-mirror with mode=existing and always for
|
||||
blockdev-mirror.
|
||||
|
||||
Note that we only have to zero-initialize the target with sync=full,
|
||||
because other modes actually do not promise that the target will contain
|
||||
the same data as the source after the job -- sync=top only promises to
|
||||
copy anything allocated in the top layer, and sync=none will only copy
|
||||
new I/O. (Which is how mirror has always handled it.)
|
||||
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190724171239.8764-3-mreitz@redhat.com
|
||||
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
---
|
||||
block/mirror.c | 11 ++++++++---
|
||||
blockdev.c | 16 +++++++++++++---
|
||||
include/block/block_int.h | 2 ++
|
||||
tests/test-block-iothread.c | 2 +-
|
||||
4 files changed, 24 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/block/mirror.c b/block/mirror.c
|
||||
index ccae49a28e..89a053b265 100644
|
||||
--- a/block/mirror.c
|
||||
+++ b/block/mirror.c
|
||||
@@ -51,6 +51,8 @@ typedef struct MirrorBlockJob {
|
||||
Error *replace_blocker;
|
||||
bool is_none_mode;
|
||||
BlockMirrorBackingMode backing_mode;
|
||||
+ /* Whether the target image requires explicit zero-initialization */
|
||||
+ bool zero_target;
|
||||
MirrorCopyMode copy_mode;
|
||||
BlockdevOnError on_source_error, on_target_error;
|
||||
bool synced;
|
||||
@@ -779,7 +781,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
|
||||
int ret;
|
||||
int64_t count;
|
||||
|
||||
- if (base == NULL && !bdrv_has_zero_init(target_bs)) {
|
||||
+ if (s->zero_target) {
|
||||
if (!bdrv_can_write_zeroes_with_unmap(target_bs)) {
|
||||
bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length);
|
||||
return 0;
|
||||
@@ -1531,6 +1533,7 @@ static BlockJob *mirror_start_job(
|
||||
const char *replaces, int64_t speed,
|
||||
uint32_t granularity, int64_t buf_size,
|
||||
BlockMirrorBackingMode backing_mode,
|
||||
+ bool zero_target,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
bool unmap,
|
||||
@@ -1658,6 +1661,7 @@ static BlockJob *mirror_start_job(
|
||||
s->on_target_error = on_target_error;
|
||||
s->is_none_mode = is_none_mode;
|
||||
s->backing_mode = backing_mode;
|
||||
+ s->zero_target = zero_target;
|
||||
s->copy_mode = copy_mode;
|
||||
s->base = base;
|
||||
s->granularity = granularity;
|
||||
@@ -1762,6 +1766,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
int creation_flags, int64_t speed,
|
||||
uint32_t granularity, int64_t buf_size,
|
||||
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
|
||||
+ bool zero_target,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
bool unmap, const char *filter_node_name,
|
||||
@@ -1779,7 +1784,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
|
||||
base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL;
|
||||
mirror_start_job(job_id, bs, creation_flags, target, replaces,
|
||||
- speed, granularity, buf_size, backing_mode,
|
||||
+ 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);
|
||||
@@ -1806,7 +1811,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
|
||||
ret = mirror_start_job(
|
||||
job_id, bs, creation_flags, base, NULL, speed, 0, 0,
|
||||
- MIRROR_LEAVE_BACKING_CHAIN,
|
||||
+ MIRROR_LEAVE_BACKING_CHAIN, false,
|
||||
on_error, on_error, true, cb, opaque,
|
||||
&commit_active_job_driver, false, base, auto_complete,
|
||||
filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND,
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 94e5aee30b..4435795b6d 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3739,6 +3739,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
||||
bool has_replaces, const char *replaces,
|
||||
enum MirrorSyncMode sync,
|
||||
BlockMirrorBackingMode backing_mode,
|
||||
+ bool zero_target,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_granularity, uint32_t granularity,
|
||||
bool has_buf_size, int64_t buf_size,
|
||||
@@ -3847,7 +3848,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
||||
*/
|
||||
mirror_start(job_id, bs, target,
|
||||
has_replaces ? replaces : NULL, job_flags,
|
||||
- speed, granularity, buf_size, sync, backing_mode,
|
||||
+ speed, granularity, buf_size, sync, backing_mode, zero_target,
|
||||
on_source_error, on_target_error, unmap, filter_node_name,
|
||||
copy_mode, errp);
|
||||
}
|
||||
@@ -3863,6 +3864,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
int flags;
|
||||
int64_t size;
|
||||
const char *format = arg->format;
|
||||
+ bool zero_target;
|
||||
int ret;
|
||||
|
||||
bs = qmp_get_root_bs(arg->device, errp);
|
||||
@@ -3964,6 +3966,10 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ zero_target = (arg->sync == MIRROR_SYNC_MODE_FULL &&
|
||||
+ (arg->mode == NEW_IMAGE_MODE_EXISTING ||
|
||||
+ !bdrv_has_zero_init(target_bs)));
|
||||
+
|
||||
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_unref(target_bs);
|
||||
@@ -3972,7 +3978,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
|
||||
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
|
||||
arg->has_replaces, arg->replaces, arg->sync,
|
||||
- backing_mode, arg->has_speed, arg->speed,
|
||||
+ backing_mode, zero_target,
|
||||
+ arg->has_speed, arg->speed,
|
||||
arg->has_granularity, arg->granularity,
|
||||
arg->has_buf_size, arg->buf_size,
|
||||
arg->has_on_source_error, arg->on_source_error,
|
||||
@@ -4012,6 +4019,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
AioContext *aio_context;
|
||||
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
|
||||
Error *local_err = NULL;
|
||||
+ bool zero_target;
|
||||
int ret;
|
||||
|
||||
bs = qmp_get_root_bs(device, errp);
|
||||
@@ -4024,6 +4032,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
return;
|
||||
}
|
||||
|
||||
+ zero_target = (sync == MIRROR_SYNC_MODE_FULL);
|
||||
+
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
@@ -4034,7 +4044,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
|
||||
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
|
||||
has_replaces, replaces, sync, backing_mode,
|
||||
- has_speed, speed,
|
||||
+ zero_target, has_speed, speed,
|
||||
has_granularity, granularity,
|
||||
has_buf_size, buf_size,
|
||||
has_on_source_error, on_source_error,
|
||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
||||
index 76117a761a..154b9b5501 100644
|
||||
--- a/include/block/block_int.h
|
||||
+++ b/include/block/block_int.h
|
||||
@@ -1120,6 +1120,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
* @buf_size: The amount of data that can be in flight at one time.
|
||||
* @mode: Whether to collapse all images in the chain to the target.
|
||||
* @backing_mode: How to establish the target's backing chain after completion.
|
||||
+ * @zero_target: Whether the target should be explicitly zero-initialized
|
||||
* @on_source_error: The action to take upon error reading from the source.
|
||||
* @on_target_error: The action to take upon error writing to the target.
|
||||
* @unmap: Whether to unmap target where source sectors only contain zeroes.
|
||||
@@ -1139,6 +1140,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
int creation_flags, int64_t speed,
|
||||
uint32_t granularity, int64_t buf_size,
|
||||
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
|
||||
+ bool zero_target,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
bool unmap, const char *filter_node_name,
|
||||
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
|
||||
index 1949d5e61a..debfb69bfb 100644
|
||||
--- a/tests/test-block-iothread.c
|
||||
+++ b/tests/test-block-iothread.c
|
||||
@@ -611,7 +611,7 @@ static void test_propagate_mirror(void)
|
||||
|
||||
/* Start a mirror job */
|
||||
mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0,
|
||||
- MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN,
|
||||
+ MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false,
|
||||
BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
|
||||
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
|
||||
&error_abort);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
54
qapi-add-BitmapSyncMode-enum.patch
Normal file
54
qapi-add-BitmapSyncMode-enum.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From bd1d5d79f4629520d0753676cea8129c60fc6bbc Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:52 -0400
|
||||
Subject: [PATCH] qapi: add BitmapSyncMode enum
|
||||
|
||||
Depending on what a user is trying to accomplish, there might be a few
|
||||
bitmap cleanup actions that occur when an operation is finished that
|
||||
could be useful.
|
||||
|
||||
I am proposing three:
|
||||
- NEVER: The bitmap is never synchronized against what was copied.
|
||||
- ALWAYS: The bitmap is always synchronized, even on failures.
|
||||
- ON-SUCCESS: The bitmap is synchronized only on success.
|
||||
|
||||
The existing incremental backup modes use 'on-success' semantics,
|
||||
so add just that one for right now.
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Reviewed-by: Markus Armbruster <armbru@redhat.com>
|
||||
Message-id: 20190709232550.10724-5-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
qapi/block-core.json | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
||||
index 37aa1b7b9a..b8d12a4951 100644
|
||||
--- a/qapi/block-core.json
|
||||
+++ b/qapi/block-core.json
|
||||
@@ -1134,6 +1134,20 @@
|
||||
{ 'enum': 'MirrorSyncMode',
|
||||
'data': ['top', 'full', 'none', 'incremental'] }
|
||||
|
||||
+##
|
||||
+# @BitmapSyncMode:
|
||||
+#
|
||||
+# An enumeration of possible behaviors for the synchronization of a bitmap
|
||||
+# when used for data copy operations.
|
||||
+#
|
||||
+# @on-success: The bitmap is only synced when the operation is successful.
|
||||
+# This is the behavior always used for 'INCREMENTAL' backups.
|
||||
+#
|
||||
+# Since: 4.2
|
||||
+##
|
||||
+{ 'enum': 'BitmapSyncMode',
|
||||
+ 'data': ['on-success'] }
|
||||
+
|
||||
##
|
||||
# @MirrorCopyMode:
|
||||
#
|
||||
--
|
||||
2.27.0
|
||||
|
||||
171
qapi-block-core-Introduce-BackupCommon.patch
Normal file
171
qapi-block-core-Introduce-BackupCommon.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From 2204b4839fb90658e13ddc608df7b35ed1ea9fd0 Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 16:35:52 -0400
|
||||
Subject: [PATCH] qapi/block-core: Introduce BackupCommon
|
||||
|
||||
drive-backup and blockdev-backup have an awful lot of things in common
|
||||
that are the same. Let's fix that.
|
||||
|
||||
I don't deduplicate 'target', because the semantics actually did change
|
||||
between each structure. Leave that one alone so it can be documented
|
||||
separately.
|
||||
|
||||
Where documentation was not identical, use the most up-to-date version.
|
||||
For "speed", use Blockdev-Backup's version. For "sync", use
|
||||
Drive-Backup's version.
|
||||
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
[Maintainer edit: modified commit message. --js]
|
||||
Reviewed-by: Markus Armbruster <armbru@redhat.com>
|
||||
Message-id: 20190709232550.10724-2-jsnow@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
---
|
||||
qapi/block-core.json | 95 ++++++++++++++------------------------------
|
||||
1 file changed, 29 insertions(+), 66 deletions(-)
|
||||
|
||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
||||
index db24f0dfe5..37aa1b7b9a 100644
|
||||
--- a/qapi/block-core.json
|
||||
+++ b/qapi/block-core.json
|
||||
@@ -1315,32 +1315,23 @@
|
||||
'data': { 'node': 'str', 'overlay': 'str' } }
|
||||
|
||||
##
|
||||
-# @DriveBackup:
|
||||
+# @BackupCommon:
|
||||
#
|
||||
# @job-id: identifier for the newly-created block job. If
|
||||
# omitted, the device name will be used. (Since 2.7)
|
||||
#
|
||||
# @device: the device name or node-name of a root node which should be copied.
|
||||
#
|
||||
-# @target: the target of the new image. If the file exists, or if it
|
||||
-# is a device, the existing file/device will be used as the new
|
||||
-# destination. If it does not exist, a new file will be created.
|
||||
-#
|
||||
-# @format: the format of the new destination, default is to
|
||||
-# probe if @mode is 'existing', else the format of the source
|
||||
-#
|
||||
# @sync: what parts of the disk image should be copied to the destination
|
||||
# (all the disk, only the sectors allocated in the topmost image, from a
|
||||
# dirty bitmap, or only new I/O).
|
||||
#
|
||||
-# @mode: whether and how QEMU should create a new image, default is
|
||||
-# 'absolute-paths'.
|
||||
-#
|
||||
-# @speed: the maximum speed, in bytes per second
|
||||
+# @speed: the maximum speed, in bytes per second. The default is 0,
|
||||
+# for unlimited.
|
||||
#
|
||||
# @bitmap: the name of dirty bitmap if sync is "incremental".
|
||||
# Must be present if sync is "incremental", must NOT be present
|
||||
-# otherwise. (Since 2.4)
|
||||
+# otherwise. (Since 2.4 (drive-backup), 3.1 (blockdev-backup))
|
||||
#
|
||||
# @compress: true to compress data, if the target format supports it.
|
||||
# (default: false) (since 2.8)
|
||||
@@ -1370,75 +1361,47 @@
|
||||
# I/O. If an error occurs during a guest write request, the device's
|
||||
# rerror/werror actions will be used.
|
||||
#
|
||||
-# Since: 1.6
|
||||
+# Since: 4.2
|
||||
##
|
||||
-{ 'struct': 'DriveBackup',
|
||||
- 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
|
||||
- '*format': 'str', 'sync': 'MirrorSyncMode',
|
||||
- '*mode': 'NewImageMode', '*speed': 'int',
|
||||
+{ 'struct': 'BackupCommon',
|
||||
+ 'data': { '*job-id': 'str', 'device': 'str',
|
||||
+ 'sync': 'MirrorSyncMode', '*speed': 'int',
|
||||
'*bitmap': 'str', '*compress': 'bool',
|
||||
'*on-source-error': 'BlockdevOnError',
|
||||
'*on-target-error': 'BlockdevOnError',
|
||||
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
|
||||
|
||||
##
|
||||
-# @BlockdevBackup:
|
||||
-#
|
||||
-# @job-id: identifier for the newly-created block job. If
|
||||
-# omitted, the device name will be used. (Since 2.7)
|
||||
-#
|
||||
-# @device: the device name or node-name of a root node which should be copied.
|
||||
-#
|
||||
-# @target: the device name or node-name of the backup target node.
|
||||
-#
|
||||
-# @sync: what parts of the disk image should be copied to the destination
|
||||
-# (all the disk, only the sectors allocated in the topmost image, or
|
||||
-# only new I/O).
|
||||
-#
|
||||
-# @speed: the maximum speed, in bytes per second. The default is 0,
|
||||
-# for unlimited.
|
||||
-#
|
||||
-# @bitmap: the name of dirty bitmap if sync is "incremental".
|
||||
-# Must be present if sync is "incremental", must NOT be present
|
||||
-# otherwise. (Since 3.1)
|
||||
-#
|
||||
-# @compress: true to compress data, if the target format supports it.
|
||||
-# (default: false) (since 2.8)
|
||||
+# @DriveBackup:
|
||||
#
|
||||
-# @on-source-error: the action to take on an error on the source,
|
||||
-# default 'report'. 'stop' and 'enospc' can only be used
|
||||
-# if the block device supports io-status (see BlockInfo).
|
||||
+# @target: the target of the new image. If the file exists, or if it
|
||||
+# is a device, the existing file/device will be used as the new
|
||||
+# destination. If it does not exist, a new file will be created.
|
||||
#
|
||||
-# @on-target-error: the action to take on an error on the target,
|
||||
-# default 'report' (no limitations, since this applies to
|
||||
-# a different block device than @device).
|
||||
+# @format: the format of the new destination, default is to
|
||||
+# probe if @mode is 'existing', else the format of the source
|
||||
#
|
||||
-# @auto-finalize: When false, this job will wait in a PENDING state after it has
|
||||
-# finished its work, waiting for @block-job-finalize before
|
||||
-# making any block graph changes.
|
||||
-# When true, this job will automatically
|
||||
-# perform its abort or commit actions.
|
||||
-# Defaults to true. (Since 2.12)
|
||||
+# @mode: whether and how QEMU should create a new image, default is
|
||||
+# 'absolute-paths'.
|
||||
#
|
||||
-# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it
|
||||
-# has completely ceased all work, and awaits @block-job-dismiss.
|
||||
-# When true, this job will automatically disappear from the query
|
||||
-# list without user intervention.
|
||||
-# Defaults to true. (Since 2.12)
|
||||
+# Since: 1.6
|
||||
+##
|
||||
+{ 'struct': 'DriveBackup',
|
||||
+ 'base': 'BackupCommon',
|
||||
+ 'data': { 'target': 'str',
|
||||
+ '*format': 'str',
|
||||
+ '*mode': 'NewImageMode' } }
|
||||
+
|
||||
+##
|
||||
+# @BlockdevBackup:
|
||||
#
|
||||
-# Note: @on-source-error and @on-target-error only affect background
|
||||
-# I/O. If an error occurs during a guest write request, the device's
|
||||
-# rerror/werror actions will be used.
|
||||
+# @target: the device name or node-name of the backup target node.
|
||||
#
|
||||
# Since: 2.3
|
||||
##
|
||||
{ 'struct': 'BlockdevBackup',
|
||||
- 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
|
||||
- 'sync': 'MirrorSyncMode', '*speed': 'int',
|
||||
- '*bitmap': 'str', '*compress': 'bool',
|
||||
- '*on-source-error': 'BlockdevOnError',
|
||||
- '*on-target-error': 'BlockdevOnError',
|
||||
- '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
|
||||
+ 'base': 'BackupCommon',
|
||||
+ 'data': { 'target': 'str' } }
|
||||
|
||||
##
|
||||
# @blockdev-snapshot-sync:
|
||||
--
|
||||
2.27.0
|
||||
|
||||
46
qemu.spec
46
qemu.spec
@ -1,6 +1,6 @@
|
||||
Name: qemu
|
||||
Version: 4.1.0
|
||||
Release: 68
|
||||
Release: 69
|
||||
Epoch: 2
|
||||
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
||||
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
|
||||
@ -391,6 +391,25 @@ Patch0378: target-i386-enable-monitor-and-ucode-revision-with-c.patch
|
||||
Patch0379: target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch
|
||||
Patch0380: target-i386-kvm-initialize-feature-MSRs-very-early.patch
|
||||
Patch0381: target-i386-add-a-ucode-rev-property.patch
|
||||
Patch0382: migration-use-migration_is_active-to-represent-activ.patch
|
||||
Patch0383: migration-Rate-limit-inside-host-pages.patch
|
||||
Patch0384: hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch
|
||||
Patch0385: qapi-block-core-Introduce-BackupCommon.patch
|
||||
Patch0386: drive-backup-create-do_backup_common.patch
|
||||
Patch0387: blockdev-backup-utilize-do_backup_common.patch
|
||||
Patch0388: qapi-add-BitmapSyncMode-enum.patch
|
||||
Patch0389: block-backup-Add-mirror-sync-mode-bitmap.patch
|
||||
Patch0390: block-backup-add-never-policy-to-bitmap-sync-mode.patch
|
||||
Patch0391: block-backup-loosen-restriction-on-readonly-bitmaps.patch
|
||||
Patch0392: block-backup-hoist-bitmap-check-into-QMP-interface.patch
|
||||
Patch0393: block-backup-deal-with-zero-detection.patch
|
||||
Patch0394: mirror-Fix-bdrv_has_zero_init-use.patch
|
||||
Patch0395: blockdev-fix-coding-style-issues-in-drive_backup_pre.patch
|
||||
Patch0396: blockdev-unify-qmp_drive_backup-and-drive-backup-tra.patch
|
||||
Patch0397: blockdev-unify-qmp_blockdev_backup-and-blockdev-back.patch
|
||||
Patch0398: blockdev-honor-bdrv_try_set_aio_context-context-requ.patch
|
||||
Patch0399: blockdev-Return-bs-to-the-proper-context-on-snapshot.patch
|
||||
Patch0400: block-Fix-cross-AioContext-blockdev-snapshot.patch
|
||||
|
||||
BuildRequires: flex
|
||||
BuildRequires: gcc
|
||||
@ -785,6 +804,31 @@ getent passwd qemu >/dev/null || \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Jul 22 2021 Chen Qun <kuhn.chenqun@huawei.com>
|
||||
- qapi/block-core: Introduce BackupCommon
|
||||
- drive-backup: create do_backup_common
|
||||
- blockdev-backup: utilize do_backup_common
|
||||
- qapi: add BitmapSyncMode enum
|
||||
- block/backup: Add mirror sync mode 'bitmap'
|
||||
- block/backup: add 'never' policy to bitmap sync mode
|
||||
- block/backup: loosen restriction on readonly bitmaps
|
||||
- block/backup: hoist bitmap check into QMP interface
|
||||
- block/backup: deal with zero detection
|
||||
- mirror: Fix bdrv_has_zero_init() use
|
||||
- blockdev: fix coding style issues in drive_backup_prepare
|
||||
- blockdev: unify qmp_drive_backup and drive-backup transaction paths
|
||||
- blockdev: unify qmp_blockdev_backup and blockdev-backup transaction paths
|
||||
- blockdev: honor bdrv_try_set_aio_context() context requirements
|
||||
- blockdev: Return bs to the proper context on snapshot abort
|
||||
- block: Fix cross-AioContext blockdev-snapshot
|
||||
|
||||
* Thu Jul 22 2021 Chen Qun <kuhn.chenqun@huawei.com>
|
||||
- hw/pci/pcie: Move hot plug capability check to pre_plug callback
|
||||
|
||||
* Thu Jul 22 2021 Chen Qun <kuhn.chenqun@huawei.com>
|
||||
- migration: use migration_is_active to represent active state
|
||||
- migration: Rate limit inside host pages
|
||||
|
||||
* Thu Jul 22 2021 Chen Qun <kuhn.chenqun@huawei.com>
|
||||
- virtio-net: delete also control queue when TX/RX deleted
|
||||
- target/i386: enable monitor and ucode revision with -cpu max
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user