libvirt-11.10.0-5.el9
- qemublocktest: Iterate all nodenames in 'testQemuDetectBitmaps' (RHEL-145770) - qemu: monitor: Detect list of bitmaps from 'qcow2' format specific data (RHEL-145770) - qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Fix check for existing bitmaps (RHEL-145770) - qemu: migration: Always offer block dirty bitmaps during migration (RHEL-145770) - qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Always consider offered bitmaps (RHEL-145770) Resolves: RHEL-145770
This commit is contained in:
parent
83aad8ea81
commit
ad543367fd
@ -0,0 +1,147 @@
|
||||
From d2c2c9bf6cb12cd1bd02763410744c8322c36bdc Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <d2c2c9bf6cb12cd1bd02763410744c8322c36bdc.1770203323.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Tue, 27 Jan 2026 17:00:10 +0100
|
||||
Subject: [PATCH] qemu: migration: Always offer block dirty bitmaps during
|
||||
migration
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Until now block dirty bitmaps were offered to destination only if
|
||||
non-shared storage migration was enabled.
|
||||
|
||||
Upcoming patches will want to support it also in cases when storage is
|
||||
shared but the destination has a qcow2 overlay using the 'data_file'
|
||||
feature where the qcow2 overlay is not actually shared.
|
||||
|
||||
To support that we'll now always offer bitmaps for migration. The
|
||||
destination can then decide (using existing logic) to pick only the
|
||||
ones that are not present in the image on destination, which is how
|
||||
it was supposed to work even now.
|
||||
|
||||
The patch removes all the flag checks and simply offers bitmaps in any
|
||||
case. The overhead incurred by this is one 'query-named-block-nodes'
|
||||
call to qemu.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit a4f610ff3fe190058f18baea18b095d0bc69441b)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
|
||||
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
|
||||
---
|
||||
src/qemu/qemu_migration.c | 28 +++++++---------------------
|
||||
1 file changed, 7 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
||||
index 723e131c98..755b9a5e1a 100644
|
||||
--- a/src/qemu/qemu_migration.c
|
||||
+++ b/src/qemu/qemu_migration.c
|
||||
@@ -2580,16 +2580,13 @@ qemuMigrationAnyConnectionClosed(virDomainObj *vm,
|
||||
* qemuMigrationSrcBeginPhaseBlockDirtyBitmaps:
|
||||
* @mig: migration cookie struct
|
||||
* @vm: domain object
|
||||
- * @migrate_disks: disks which are being migrated
|
||||
- * @nmigrage_disks: number of @migrate_disks
|
||||
*
|
||||
* Enumerates block dirty bitmaps on disks which will undergo storage migration
|
||||
* and fills them into @mig to be offered to the destination.
|
||||
*/
|
||||
static int
|
||||
qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(qemuMigrationCookie *mig,
|
||||
- virDomainObj *vm,
|
||||
- const char **migrate_disks)
|
||||
+ virDomainObj *vm)
|
||||
|
||||
{
|
||||
GSList *disks = NULL;
|
||||
@@ -2611,9 +2608,6 @@ qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(qemuMigrationCookie *mig,
|
||||
if (!nodedata)
|
||||
continue;
|
||||
|
||||
- if (!qemuMigrationAnyCopyDisk(diskdef, migrate_disks))
|
||||
- continue;
|
||||
-
|
||||
for (j = 0; j < nodedata->nbitmaps; j++) {
|
||||
qemuMigrationBlockDirtyBitmapsDiskBitmap *bitmap;
|
||||
|
||||
@@ -2680,7 +2674,6 @@ qemuMigrationSrcBeginXML(virDomainObj *vm,
|
||||
char **cookieout,
|
||||
int *cookieoutlen,
|
||||
unsigned int cookieFlags,
|
||||
- const char **migrate_disks,
|
||||
unsigned int flags)
|
||||
{
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
@@ -2696,8 +2689,7 @@ qemuMigrationSrcBeginXML(virDomainObj *vm,
|
||||
if (!(mig = qemuMigrationCookieNew(vm->def, priv->origname)))
|
||||
return NULL;
|
||||
|
||||
- if (cookieFlags & QEMU_MIGRATION_COOKIE_NBD &&
|
||||
- qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(mig, vm, migrate_disks) < 0)
|
||||
+ if (qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(mig, vm) < 0)
|
||||
return NULL;
|
||||
|
||||
if (qemuMigrationCookieFormat(mig, driver, vm,
|
||||
@@ -2879,8 +2871,7 @@ qemuMigrationSrcBeginPhase(virQEMUDriver *driver,
|
||||
return NULL;
|
||||
|
||||
return qemuMigrationSrcBeginXML(vm, xmlin,
|
||||
- cookieout, cookieoutlen, cookieFlags,
|
||||
- migrate_disks, flags);
|
||||
+ cookieout, cookieoutlen, cookieFlags, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -2969,8 +2960,7 @@ qemuMigrationSrcBeginResume(virDomainObj *vm,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- return qemuMigrationSrcBeginXML(vm, xmlin,
|
||||
- cookieout, cookieoutlen, 0, NULL, flags);
|
||||
+ return qemuMigrationSrcBeginXML(vm, xmlin, cookieout, cookieoutlen, 0, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -4752,7 +4742,6 @@ qemuMigrationSrcRunPrepareBlockDirtyBitmaps(virDomainObj *vm,
|
||||
|
||||
/* For VIR_MIGRATE_NON_SHARED_INC we can migrate the bitmaps directly,
|
||||
* otherwise we must create merged bitmaps from the whole chain */
|
||||
-
|
||||
if (!(flags & VIR_MIGRATE_NON_SHARED_INC) &&
|
||||
qemuMigrationSrcRunPrepareBlockDirtyBitmapsMerge(vm, mig) < 0)
|
||||
return -1;
|
||||
@@ -4943,7 +4932,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
|
||||
VIR_AUTOCLOSE fd = -1;
|
||||
unsigned long restore_max_bandwidth = priv->migMaxBandwidth;
|
||||
virErrorPtr orig_err = NULL;
|
||||
- unsigned int cookieFlags = 0;
|
||||
+ unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS;
|
||||
bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
|
||||
bool storageMigration = flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC);
|
||||
bool cancel = false;
|
||||
@@ -4967,10 +4956,8 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
|
||||
storageMigration = qemuMigrationHasAnyStorageMigrationDisks(vm->def,
|
||||
migrate_disks);
|
||||
|
||||
- if (storageMigration) {
|
||||
+ if (storageMigration)
|
||||
cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
|
||||
- cookieFlags |= QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS;
|
||||
- }
|
||||
|
||||
if (virLockManagerPluginUsesState(driver->lockManager) &&
|
||||
!cookieout) {
|
||||
@@ -5004,8 +4991,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
|
||||
cookiein, cookieinlen,
|
||||
cookieFlags |
|
||||
QEMU_MIGRATION_COOKIE_GRAPHICS |
|
||||
- QEMU_MIGRATION_COOKIE_CAPS |
|
||||
- QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS);
|
||||
+ QEMU_MIGRATION_COOKIE_CAPS);
|
||||
if (!mig)
|
||||
goto error;
|
||||
|
||||
--
|
||||
2.52.0
|
||||
@ -0,0 +1,173 @@
|
||||
From 94768f63a02ec5e9f25cb5db28b38ed6950c1df0 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <94768f63a02ec5e9f25cb5db28b38ed6950c1df0.1770203323.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Tue, 27 Jan 2026 20:07:32 +0100
|
||||
Subject: [PATCH] qemu: monitor: Detect list of bitmaps from 'qcow2' format
|
||||
specific data
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We currently probe dirty block tracking bitmaps by looking at the loaded
|
||||
ones ('dirty-bitmaps'). Unfortunately those may not yet be populated on
|
||||
incoming migration when the image was not yet activated, but we need to
|
||||
know which ones are stored in the image so that we don't migrate those
|
||||
explicitly, which would fail.
|
||||
|
||||
Load the list of bitmaps in a qcow2 image from the format specific data,
|
||||
which is already loaded at that point.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit b2fe3465de1db033e436f38fdd24648c8c884a3d)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
|
||||
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
|
||||
---
|
||||
src/qemu/qemu_monitor.h | 4 ++++
|
||||
src/qemu/qemu_monitor_json.c | 17 +++++++++++++++++
|
||||
tests/qemublocktest.c | 11 +++++++++++
|
||||
tests/qemublocktestdata/bitmap/snapshots.out | 5 +++++
|
||||
tests/qemublocktestdata/bitmap/synthetic.out | 4 ++++
|
||||
5 files changed, 41 insertions(+)
|
||||
|
||||
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
|
||||
index d096f474c1..041aa7bc12 100644
|
||||
--- a/src/qemu/qemu_monitor.h
|
||||
+++ b/src/qemu/qemu_monitor.h
|
||||
@@ -893,8 +893,12 @@ struct _qemuBlockNamedNodeData {
|
||||
unsigned long long capacity;
|
||||
unsigned long long physical;
|
||||
|
||||
+ /* Information about change block tracking bitmaps which are active and loaded */
|
||||
qemuBlockNamedNodeDataBitmap **bitmaps;
|
||||
size_t nbitmaps;
|
||||
+ /* With qcow2 we have also a separate list of bitmaps present in the image
|
||||
+ * but not yet activated, which happens when starting qemu during migration */
|
||||
+ char **qcow2bitmaps;
|
||||
|
||||
/* hash table indexed by snapshot name containing data about snapshots
|
||||
* (qemuBlockNamedNodeDataSnapshot) */
|
||||
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
||||
index 494d7ef515..401a28ff9a 100644
|
||||
--- a/src/qemu/qemu_monitor_json.c
|
||||
+++ b/src/qemu/qemu_monitor_json.c
|
||||
@@ -2730,6 +2730,7 @@ qemuMonitorJSONBlockNamedNodeDataFree(qemuBlockNamedNodeData *data)
|
||||
qemuMonitorJSONBlockNamedNodeDataBitmapFree(data->bitmaps[i]);
|
||||
g_clear_pointer(&data->snapshots, g_hash_table_unref);
|
||||
g_free(data->bitmaps);
|
||||
+ g_strfreev(data->qcow2bitmaps);
|
||||
g_free(data);
|
||||
}
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuBlockNamedNodeData, qemuMonitorJSONBlockNamedNodeDataFree);
|
||||
@@ -2854,6 +2855,9 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos G_GNUC_UNUSED,
|
||||
virJSONValue *qcow2props = virJSONValueObjectGetObject(format_specific, "data");
|
||||
|
||||
if (qcow2props) {
|
||||
+ virJSONValue *bmp;
|
||||
+ size_t nbmp;
|
||||
+
|
||||
if (STREQ_NULLABLE(virJSONValueObjectGetString(qcow2props, "compat"), "0.10"))
|
||||
ent->qcow2v2 = true;
|
||||
|
||||
@@ -2862,6 +2866,19 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos G_GNUC_UNUSED,
|
||||
|
||||
ignore_value(virJSONValueObjectGetBoolean(qcow2props, "data-file-raw",
|
||||
&ent->qcow2dataFileRaw));
|
||||
+
|
||||
+ if ((bmp = virJSONValueObjectGetArray(qcow2props, "bitmaps")) &&
|
||||
+ ((nbmp = virJSONValueArraySize(bmp)) > 0)) {
|
||||
+ size_t i;
|
||||
+
|
||||
+ ent->qcow2bitmaps = g_new0(char *, nbmp + 1);
|
||||
+
|
||||
+ for (i = 0; i < nbmp; i++) {
|
||||
+ virJSONValue *b = virJSONValueArrayGet(bmp, i);
|
||||
+
|
||||
+ ent->qcow2bitmaps[i] = g_strdup(virJSONValueObjectGetString(b, "name"));
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
|
||||
index 51d9268cdd..18ec90edf5 100644
|
||||
--- a/tests/qemublocktest.c
|
||||
+++ b/tests/qemublocktest.c
|
||||
@@ -600,6 +600,17 @@ testQemuDetectBitmapsWorker(void *payload,
|
||||
bitmap->granularity, bitmap->dirtybytes);
|
||||
}
|
||||
|
||||
+ if (data->qcow2bitmaps) {
|
||||
+ char **b;
|
||||
+
|
||||
+ virBufferAddLit(buf, "qcow2 bitmaps:");
|
||||
+
|
||||
+ for (b = data->qcow2bitmaps; *b; b++)
|
||||
+ virBufferAsprintf(buf, " %s", *b);
|
||||
+
|
||||
+ virBufferAddLit(buf, "\n");
|
||||
+ }
|
||||
+
|
||||
if (data->snapshots) {
|
||||
g_autofree virHashKeyValuePair *snaps = virHashGetItems(data->snapshots, NULL, true);
|
||||
virHashKeyValuePair *n;
|
||||
diff --git a/tests/qemublocktestdata/bitmap/snapshots.out b/tests/qemublocktestdata/bitmap/snapshots.out
|
||||
index 29c586be7e..dedd77465c 100644
|
||||
--- a/tests/qemublocktestdata/bitmap/snapshots.out
|
||||
+++ b/tests/qemublocktestdata/bitmap/snapshots.out
|
||||
@@ -4,21 +4,26 @@ libvirt-1-format:
|
||||
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
current: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: current c b a d
|
||||
libvirt-1-storage:
|
||||
libvirt-2-format:
|
||||
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: d a b c
|
||||
libvirt-2-storage:
|
||||
libvirt-3-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: c b a
|
||||
libvirt-3-storage:
|
||||
libvirt-4-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: a
|
||||
libvirt-4-storage:
|
||||
libvirt-5-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: a
|
||||
libvirt-5-storage:
|
||||
diff --git a/tests/qemublocktestdata/bitmap/synthetic.out b/tests/qemublocktestdata/bitmap/synthetic.out
|
||||
index 2f4ae2b217..0a47a90107 100644
|
||||
--- a/tests/qemublocktestdata/bitmap/synthetic.out
|
||||
+++ b/tests/qemublocktestdata/bitmap/synthetic.out
|
||||
@@ -6,17 +6,21 @@ libvirt-1-format:
|
||||
top-inactive: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
top-transient: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
|
||||
top-transient-inactive: record:0 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: current
|
||||
libvirt-1-storage:
|
||||
libvirt-2-format:
|
||||
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: d
|
||||
libvirt-2-storage:
|
||||
libvirt-3-format:
|
||||
b: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
|
||||
c: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: c b
|
||||
libvirt-3-storage:
|
||||
libvirt-4-format:
|
||||
libvirt-4-storage:
|
||||
libvirt-5-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+ qcow2 bitmaps: a
|
||||
libvirt-5-storage:
|
||||
--
|
||||
2.52.0
|
||||
@ -0,0 +1,98 @@
|
||||
From 73e383336be99821e588ef0fb8a6da8ad9fa7414 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <73e383336be99821e588ef0fb8a6da8ad9fa7414.1770203323.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Tue, 27 Jan 2026 17:28:48 +0100
|
||||
Subject: [PATCH] qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Always consider
|
||||
offered bitmaps
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Consider bitmaps for incoming migration regardless of non-shared storage
|
||||
flag.
|
||||
|
||||
When bitmaps are offered from the source, consult the local image if the
|
||||
bitmap is present and if not accept migration. Migration of bitmaps
|
||||
which exist in the qcow2 metadata is skipped because qemu rejects such
|
||||
setup (although handles it correctly in case of shared storage setup;
|
||||
see below).
|
||||
|
||||
This allows bitmap propagation for cases when the qcow2 image is not
|
||||
actually shared between destinations but the data is (using the
|
||||
data_file feature).
|
||||
|
||||
At the same time this preserves existing bitmap handling semantics for
|
||||
other cases. Specifically qemu, in case of shared storage properly
|
||||
propagates the bitmap which was already recorded in the qcow2 metadata
|
||||
on disk even if libvirt doesn't instruct migration, yet tolerates
|
||||
migration instruction if the file is not yet recorded in the on-disk
|
||||
metadata. In both cases the contents are preserved correctly.
|
||||
|
||||
When storage is not shared (which includes even cases when we migrate
|
||||
it via NBD) it's expected that the bitmaps don't exist on the
|
||||
destination and thus all will be picked for migration. We can also
|
||||
infer that this wasn't ever a problem by the fact that the code skipping
|
||||
migration of existing bitmaps was broken until recently, and qemu
|
||||
would refuse such config.
|
||||
|
||||
I've tested all the above scenarios including verifying that the
|
||||
resulting bitmaps capture dirtied regions before and after migration.
|
||||
For testing this the following command is useful:
|
||||
|
||||
virsh qemu-monitor-command --domain DOMNAME --hmp 'qemu-io -d /machine/peripheral/virtio-disk0/virtio-backend "write -P 0xcc 4M 1M"'
|
||||
|
||||
Which simulates a write from the guest side without the need to interact
|
||||
with the guest OS.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit bf34b90bb4e39b3a2fd22a5531f5ea5a95681015)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
|
||||
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
|
||||
---
|
||||
src/qemu/qemu_migration.c | 10 +++-------
|
||||
1 file changed, 3 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
||||
index 755b9a5e1a..2a4df1191d 100644
|
||||
--- a/src/qemu/qemu_migration.c
|
||||
+++ b/src/qemu/qemu_migration.c
|
||||
@@ -3183,7 +3183,6 @@ qemuMigrationDstPrepare(virQEMUDriver *driver,
|
||||
* @vm: domain object
|
||||
* @mig: migration cookie
|
||||
* @migParams: migration parameters
|
||||
- * @flags: migration flags
|
||||
*
|
||||
* Checks whether block dirty bitmaps offered by the migration source are
|
||||
* to be migrated (e.g. they don't exist, the destination is compatible etc)
|
||||
@@ -3194,16 +3193,13 @@ qemuMigrationDstPrepare(virQEMUDriver *driver,
|
||||
static int
|
||||
qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObj *vm,
|
||||
qemuMigrationCookie *mig,
|
||||
- qemuMigrationParams *migParams,
|
||||
- unsigned int flags)
|
||||
+ qemuMigrationParams *migParams)
|
||||
{
|
||||
g_autoptr(virJSONValue) mapping = NULL;
|
||||
g_autoptr(GHashTable) blockNamedNodeData = NULL;
|
||||
GSList *nextdisk;
|
||||
|
||||
- if (!mig->nbd ||
|
||||
- !mig->blockDirtyBitmaps ||
|
||||
- !(flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC)))
|
||||
+ if (!mig->blockDirtyBitmaps)
|
||||
return 0;
|
||||
|
||||
if (qemuMigrationCookieBlockDirtyBitmapsMatchDisks(vm->def, mig->blockDirtyBitmaps) < 0)
|
||||
@@ -3350,7 +3346,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver,
|
||||
goto error;
|
||||
}
|
||||
|
||||
- if (qemuMigrationDstPrepareAnyBlockDirtyBitmaps(vm, mig, migParams, flags) < 0)
|
||||
+ if (qemuMigrationDstPrepareAnyBlockDirtyBitmaps(vm, mig, migParams) < 0)
|
||||
goto error;
|
||||
|
||||
if (qemuMigrationParamsCheck(vm, VIR_ASYNC_JOB_MIGRATION_IN, migParams,
|
||||
--
|
||||
2.52.0
|
||||
@ -0,0 +1,68 @@
|
||||
From eb094db2b8112409813105d4dcc313e8ea45ee1e Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <eb094db2b8112409813105d4dcc313e8ea45ee1e.1770203323.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Tue, 27 Jan 2026 19:22:08 +0100
|
||||
Subject: [PATCH] qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Fix check for
|
||||
existing bitmaps
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On incoming migration qemu doesn't load bitmaps into memory (which makes
|
||||
them available under the 'dirty-bitmaps' field which we parse as the
|
||||
'bitmaps' array in 'qemuBlockNamedNodeData') until after actually
|
||||
resuming CPUs, thus the check for existing bitmaps never actually
|
||||
worked.
|
||||
|
||||
We need to check the 'qcow2bitmaps' field instead which is populated
|
||||
from the qcow2 headers prior to activating the image.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 0c75fc1747f039bf878ceab69cf12482ebb14095)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
|
||||
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
|
||||
---
|
||||
src/qemu/qemu_migration.c | 16 +++++++---------
|
||||
1 file changed, 7 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
||||
index 9059f9aa3a..723e131c98 100644
|
||||
--- a/src/qemu/qemu_migration.c
|
||||
+++ b/src/qemu/qemu_migration.c
|
||||
@@ -3227,6 +3227,8 @@ qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObj *vm,
|
||||
qemuBlockNamedNodeData *nodedata;
|
||||
GSList *nextbitmap;
|
||||
|
||||
+ VIR_DEBUG("offer migrate bitmaps for '%s'", disk->target);
|
||||
+
|
||||
if (!(nodedata = virHashLookup(blockNamedNodeData, disk->nodename))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("failed to find data for block node '%1$s'"),
|
||||
@@ -3243,18 +3245,14 @@ qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObj *vm,
|
||||
|
||||
for (nextbitmap = disk->bitmaps; nextbitmap; nextbitmap = nextbitmap->next) {
|
||||
qemuMigrationBlockDirtyBitmapsDiskBitmap *bitmap = nextbitmap->data;
|
||||
- size_t k;
|
||||
|
||||
/* don't migrate into existing bitmaps */
|
||||
- for (k = 0; k < nodedata->nbitmaps; k++) {
|
||||
- if (STREQ(bitmap->bitmapname, nodedata->bitmaps[k]->name)) {
|
||||
- bitmap->skip = true;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
+ if (nodedata->qcow2bitmaps)
|
||||
+ bitmap->skip = g_strv_contains((const char **) nodedata->qcow2bitmaps, bitmap->bitmapname);
|
||||
+
|
||||
+ VIR_DEBUG("offer migrate bitmap '%s' disk '%s' -> skip: '%d'",
|
||||
+ bitmap->bitmapname, disk->target, bitmap->skip);
|
||||
|
||||
- if (bitmap->skip)
|
||||
- continue;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.52.0
|
||||
@ -0,0 +1,175 @@
|
||||
From 4930e34b488c6253e8cbb5ceb2988864f7b981a0 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <4930e34b488c6253e8cbb5ceb2988864f7b981a0.1770203323.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Tue, 27 Jan 2026 22:49:09 +0100
|
||||
Subject: [PATCH] qemublocktest: Iterate all nodenames in
|
||||
'testQemuDetectBitmaps'
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Rather than looking for 30 specific nodenames (via a loop) iterate
|
||||
everything in the hash table (in a sorted order). This simplifies the
|
||||
code and provides more test outputs on previously-ignored nodenames.
|
||||
|
||||
The listing of internal snapshots in the output was also missing a
|
||||
newline, which would now cause problems with multiple images reproted.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 71643c197e86a3adc792c0b2a378a245ae6c5756)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-145769 [rhel-10.2]
|
||||
https://issues.redhat.com/browse/RHEL-145770 [rhel-9.8]
|
||||
---
|
||||
tests/qemublocktest.c | 24 +++++++------------
|
||||
tests/qemublocktestdata/bitmap/basic.out | 1 +
|
||||
tests/qemublocktestdata/bitmap/empty.out | 1 +
|
||||
.../bitmap/snapshots-internal.out | 7 ++++++
|
||||
tests/qemublocktestdata/bitmap/snapshots.out | 5 ++++
|
||||
tests/qemublocktestdata/bitmap/synthetic.out | 5 ++++
|
||||
6 files changed, 28 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
|
||||
index 47746207cc..51d9268cdd 100644
|
||||
--- a/tests/qemublocktest.c
|
||||
+++ b/tests/qemublocktest.c
|
||||
@@ -575,17 +575,15 @@ testQemuImageCreate(const void *opaque)
|
||||
|
||||
static const char *bitmapDetectPrefix = "qemublocktestdata/bitmap/";
|
||||
|
||||
-static void
|
||||
-testQemuDetectBitmapsWorker(GHashTable *nodedata,
|
||||
+static int
|
||||
+testQemuDetectBitmapsWorker(void *payload,
|
||||
const char *nodename,
|
||||
- virBuffer *buf)
|
||||
+ void *opaque)
|
||||
{
|
||||
- qemuBlockNamedNodeData *data;
|
||||
+ qemuBlockNamedNodeData *data = payload;
|
||||
+ virBuffer *buf = opaque;
|
||||
size_t i;
|
||||
|
||||
- if (!(data = virHashLookup(nodedata, nodename)))
|
||||
- return;
|
||||
-
|
||||
virBufferAsprintf(buf, "%s:\n", nodename);
|
||||
if (data->qcow2v2)
|
||||
virBufferAddLit(buf, " qcow2 v2\n");
|
||||
@@ -617,9 +615,12 @@ testQemuDetectBitmapsWorker(GHashTable *nodedata,
|
||||
|
||||
virBufferAsprintf(buf, " '%s'%s", (const char *) n->key, vms);
|
||||
}
|
||||
+
|
||||
+ virBufferAddLit(buf, "\n");
|
||||
}
|
||||
|
||||
virBufferAdjustIndent(buf, -1);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -632,7 +633,6 @@ testQemuDetectBitmaps(const void *opaque)
|
||||
g_autofree char *actual = NULL;
|
||||
g_autofree char *expectpath = NULL;
|
||||
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
||||
- size_t i;
|
||||
|
||||
expectpath = g_strdup_printf("%s/%s%s.out", abs_srcdir,
|
||||
bitmapDetectPrefix, name);
|
||||
@@ -646,13 +646,7 @@ testQemuDetectBitmaps(const void *opaque)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- /* we detect for the first 30 nodenames for simplicity */
|
||||
- for (i = 0; i < 30; i++) {
|
||||
- g_autofree char *nodename = g_strdup_printf("libvirt-%zu-format", i);
|
||||
-
|
||||
- testQemuDetectBitmapsWorker(nodedata, nodename, &buf);
|
||||
- }
|
||||
-
|
||||
+ virHashForEachSorted(nodedata, testQemuDetectBitmapsWorker, &buf);
|
||||
actual = virBufferContentAndReset(&buf);
|
||||
|
||||
return virTestCompareToFile(actual, expectpath);
|
||||
diff --git a/tests/qemublocktestdata/bitmap/basic.out b/tests/qemublocktestdata/bitmap/basic.out
|
||||
index 5c4c35b3f0..b96ffe3d39 100644
|
||||
--- a/tests/qemublocktestdata/bitmap/basic.out
|
||||
+++ b/tests/qemublocktestdata/bitmap/basic.out
|
||||
@@ -4,3 +4,4 @@ libvirt-1-format:
|
||||
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-1-storage:
|
||||
diff --git a/tests/qemublocktestdata/bitmap/empty.out b/tests/qemublocktestdata/bitmap/empty.out
|
||||
index 3787cbd354..c9a5be4f07 100644
|
||||
--- a/tests/qemublocktestdata/bitmap/empty.out
|
||||
+++ b/tests/qemublocktestdata/bitmap/empty.out
|
||||
@@ -1 +1,2 @@
|
||||
libvirt-1-format:
|
||||
+libvirt-1-storage:
|
||||
diff --git a/tests/qemublocktestdata/bitmap/snapshots-internal.out b/tests/qemublocktestdata/bitmap/snapshots-internal.out
|
||||
index dbb3cfded4..cf7bde96a5 100644
|
||||
--- a/tests/qemublocktestdata/bitmap/snapshots-internal.out
|
||||
+++ b/tests/qemublocktestdata/bitmap/snapshots-internal.out
|
||||
@@ -1,2 +1,9 @@
|
||||
libvirt-1-format:
|
||||
internal snapshots: '1727868651'(*) '1727872064'(*)
|
||||
+libvirt-1-storage:
|
||||
+libvirt-2-storage:
|
||||
+libvirt-pflash0-format:
|
||||
+libvirt-pflash0-storage:
|
||||
+libvirt-pflash1-format:
|
||||
+ internal snapshots: '1727868651' '1727872064'
|
||||
+libvirt-pflash1-storage:
|
||||
diff --git a/tests/qemublocktestdata/bitmap/snapshots.out b/tests/qemublocktestdata/bitmap/snapshots.out
|
||||
index 24ca27e4d8..29c586be7e 100644
|
||||
--- a/tests/qemublocktestdata/bitmap/snapshots.out
|
||||
+++ b/tests/qemublocktestdata/bitmap/snapshots.out
|
||||
@@ -4,16 +4,21 @@ libvirt-1-format:
|
||||
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
current: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-1-storage:
|
||||
libvirt-2-format:
|
||||
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-2-storage:
|
||||
libvirt-3-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
b: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
c: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-3-storage:
|
||||
libvirt-4-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-4-storage:
|
||||
libvirt-5-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-5-storage:
|
||||
diff --git a/tests/qemublocktestdata/bitmap/synthetic.out b/tests/qemublocktestdata/bitmap/synthetic.out
|
||||
index 45423903a0..2f4ae2b217 100644
|
||||
--- a/tests/qemublocktestdata/bitmap/synthetic.out
|
||||
+++ b/tests/qemublocktestdata/bitmap/synthetic.out
|
||||
@@ -6,12 +6,17 @@ libvirt-1-format:
|
||||
top-inactive: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
top-transient: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
|
||||
top-transient-inactive: record:0 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-1-storage:
|
||||
libvirt-2-format:
|
||||
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-2-storage:
|
||||
libvirt-3-format:
|
||||
b: record:1 busy:0 persist:0 inconsist:0 gran:65536 dirty:0
|
||||
c: record:0 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
d: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-3-storage:
|
||||
libvirt-4-format:
|
||||
+libvirt-4-storage:
|
||||
libvirt-5-format:
|
||||
a: record:1 busy:0 persist:1 inconsist:0 gran:65536 dirty:0
|
||||
+libvirt-5-storage:
|
||||
--
|
||||
2.52.0
|
||||
14
libvirt.spec
14
libvirt.spec
@ -294,7 +294,7 @@
|
||||
Summary: Library providing a simple virtualization API
|
||||
Name: libvirt
|
||||
Version: 11.10.0
|
||||
Release: 4%{?dist}%{?extra_release}
|
||||
Release: 5%{?dist}%{?extra_release}
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1
|
||||
URL: https://libvirt.org/
|
||||
|
||||
@ -323,6 +323,11 @@ Patch18: libvirt-qemuSnapshotUpdateBackingStore-Remove-stale-comment.patch
|
||||
Patch19: libvirt-qemuSnapshotDiskHasBackingDisk-Use-proper-max_depth-when-calling-virStorageSourceGetMetadata.patch
|
||||
Patch20: libvirt-virDomainSnapshotDefAssignExternalNames-Improve-error-message.patch
|
||||
Patch21: libvirt-qemuSnapshotUpdateBackingStore-Retry-as-curent-user-if-qemu-img-fails.patch
|
||||
Patch22: libvirt-qemublocktest-Iterate-all-nodenames-in-testQemuDetectBitmaps.patch
|
||||
Patch23: libvirt-qemu-monitor-Detect-list-of-bitmaps-from-qcow2-format-specific-data.patch
|
||||
Patch24: libvirt-qemuMigrationDstPrepareAnyBlockDirtyBitmaps-Fix-check-for-existing-bitmaps.patch
|
||||
Patch25: libvirt-qemu-migration-Always-offer-block-dirty-bitmaps-during-migration.patch
|
||||
Patch26: libvirt-qemuMigrationDstPrepareAnyBlockDirtyBitmaps-Always-consider-offered-bitmaps.patch
|
||||
|
||||
|
||||
Requires: libvirt-daemon = %{version}-%{release}
|
||||
@ -2714,6 +2719,13 @@ exit 0
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Feb 4 2026 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-5
|
||||
- qemublocktest: Iterate all nodenames in 'testQemuDetectBitmaps' (RHEL-145770)
|
||||
- qemu: monitor: Detect list of bitmaps from 'qcow2' format specific data (RHEL-145770)
|
||||
- qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Fix check for existing bitmaps (RHEL-145770)
|
||||
- qemu: migration: Always offer block dirty bitmaps during migration (RHEL-145770)
|
||||
- qemuMigrationDstPrepareAnyBlockDirtyBitmaps: Always consider offered bitmaps (RHEL-145770)
|
||||
|
||||
* Thu Jan 29 2026 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-4
|
||||
- qemuSecurityMoveImageMetadata: Move seclabels only to virStorageSource of same type (RHEL-140624)
|
||||
- qemuDomainSetThrottleGroup: Enforce non-zero 'groupname' string length (RHEL-144010)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user