]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: monitor: Detect list of bitmaps from 'qcow2' format specific data
authorPeter Krempa <pkrempa@redhat.com>
Tue, 27 Jan 2026 19:07:32 +0000 (20:07 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 3 Feb 2026 14:34:52 +0000 (15:34 +0100)
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>
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
tests/qemublocktest.c
tests/qemublocktestdata/bitmap/snapshots.out
tests/qemublocktestdata/bitmap/synthetic.out

index d096f474c1a50cdfde13939a3251d95c3f44b31f..041aa7bc1243f21b6fcf02775a574d85a35792a7 100644 (file)
@@ -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) */
index a602b1e65b96d0cc63c3b6fd2d8377bad6cafa8a..f3457412073185f5edc3ec0ab48620953861f56d 100644 (file)
@@ -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"));
+                }
+            }
         }
     }
 
index 51d9268cdda1db83d09183ab2187e1f66f6e16fc..18ec90edf5ef5db6a62e3c93791a7ad500e9e8b2 100644 (file)
@@ -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;
index 29c586be7e0e73f01bbb426a39e58b6d0f657365..dedd77465c527009ef5d8bcb180eea7df481968d 100644 (file)
@@ -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:
index 2f4ae2b217675601207718d8314774a5a84b29ed..0a47a90107da57b83c257ae01e7d8fa91ecf9269 100644 (file)
@@ -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: