]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemuMigrationSrcIsSafeDisk: Allow non-shared qcow2's with raw data file
authorPeter Krempa <pkrempa@redhat.com>
Tue, 9 Sep 2025 13:56:10 +0000 (15:56 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 23 Sep 2025 16:57:00 +0000 (18:57 +0200)
A qcow2 image which uses a data file and the 'data_file_raw' flag is
effectively a raw image with the qcow2 wrapper used only to store
metadata (block dirty bitmaps).

Since the dirty bitmaps are always migrated using the migration stream
it's technically not required that the qcow2 overlay itself is shared
between the destinations.

Management tools like Kubevirt want to migrate VMs which have a qcow2
overlay with the above config stored in a location that is not shared,
but the data file itself is.

This patch adds code that skips the validation of the overlay since it's
not needed to ensure data consistency in that very specific case.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_migration.c

index 2e52e73f486b9ab3e129451c848fbf6cafd115c7..7d87b3073b7639cc18aed684808f1f23a9b9e492 100644 (file)
@@ -1779,19 +1779,47 @@ qemuMigrationSrcCheckStorageSourceSafety(virStorageSource *src,
 
 
 static bool
-qemuMigrationSrcIsSafeDisk(virDomainDiskDef *disk,
+qemuMigrationSrcIsSafeDisk(virDomainObj *vm,
+                           virDomainDiskDef *disk,
                            virQEMUCaps *qemuCaps,
-                           virQEMUDriverConfig *cfg)
+                           virQEMUDriverConfig *cfg,
+                           GHashTable **blockNamedNodeData)
 {
     bool unsafe_storage = false;
     bool requires_safe_cache = false;
+    bool skip_overlay_check = false;
 
     /* Disks without any source (i.e. floppies and CD-ROMs) OR readonly are safe. */
     if (virStorageSourceIsEmpty(disk->src) ||
         disk->src->readonly)
         return true;
 
-    if (qemuMigrationSrcCheckStorageSourceSafety(disk->src, cfg, &unsafe_storage,
+    if (disk->src->dataFileStore &&
+        !virStorageSourceHasBacking(disk->src)) {
+        qemuBlockNamedNodeData *nodedata;
+
+        /* As a special case if the topmost disk image is a qcow2 with a
+         * data_file and the 'data_file_raw' option enabled, the overlay itself
+         * contains no useful data. Kubevirt uses this setup for migrations
+         * where the qcow2 overlay is used for block dirty bitmaps which are
+         * migrated using migration stream and kubevirt thus pre-creates the
+         * overlay rather than putting it on shared storage */
+
+        if (!*blockNamedNodeData &&
+            !(*blockNamedNodeData = qemuBlockGetNamedNodeData(vm,
+                                                              VIR_ASYNC_JOB_MIGRATION_OUT)))
+            return false;
+
+        if ((nodedata = virHashLookup(*blockNamedNodeData,
+                                      qemuBlockStorageSourceGetFormatNodename(disk->src)))) {
+
+            if (nodedata->qcow2dataFileRaw)
+                skip_overlay_check = true;
+        }
+    }
+
+    if (!skip_overlay_check &&
+        qemuMigrationSrcCheckStorageSourceSafety(disk->src, cfg, &unsafe_storage,
                                                  &requires_safe_cache) < 0)
         return false;
 
@@ -1831,6 +1859,7 @@ qemuMigrationSrcIsSafe(virDomainObj *vm,
 {
     qemuDomainObjPrivate *priv = vm->privateData;
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver);
+    g_autoptr(GHashTable) blockNamedNodeData = NULL;
     bool storagemigration = flags & (VIR_MIGRATE_NON_SHARED_DISK |
                                      VIR_MIGRATE_NON_SHARED_INC);
     size_t i;
@@ -1843,7 +1872,7 @@ qemuMigrationSrcIsSafe(virDomainObj *vm,
             qemuMigrationAnyCopyDisk(disk, migrate_disks))
             continue;
 
-        if (!qemuMigrationSrcIsSafeDisk(disk, priv->qemuCaps, cfg))
+        if (!qemuMigrationSrcIsSafeDisk(vm, disk, priv->qemuCaps, cfg, &blockNamedNodeData))
             return false;
     }