]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: snapshot: Propagate active bitmaps through external snapshots
authorPeter Krempa <pkrempa@redhat.com>
Thu, 28 Nov 2019 15:06:31 +0000 (16:06 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 13 Dec 2019 12:22:55 +0000 (13:22 +0100)
Re-create any active persistent bitmap in the snapshot overlay image so
that tracking for a checkpoint is persisted. While this basically
duplicates data in the allocation map it's currently the only possible
way as qemu can't mirror the allocation map into a dirty bitmap if we'd
ever want to do a backup.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
src/qemu/qemu_driver.c

index aa920c1edd9121ac1e84dfb740885cd062a28a34..accffef168685627c9f58a6533b2ac83e3aa0320 100644 (file)
@@ -15282,6 +15282,44 @@ qemuDomainSnapshotDiskCleanup(qemuDomainSnapshotDiskDataPtr data,
 }
 
 
+/**
+ * qemuDomainSnapshotDiskBitmapsPropagate:
+ *
+ * This function propagates any active persistent bitmap present in the original
+ * image into the new snapshot. This is necessary to keep tracking the changed
+ * blocks in the active bitmaps as the backing file will become read-only.
+ * We leave the original bitmap active as in cases when the overlay is
+ * discarded (snapshot revert with abandoning the history) everything works as
+ * expected.
+ */
+static int
+qemuDomainSnapshotDiskBitmapsPropagate(qemuDomainSnapshotDiskDataPtr dd,
+                                       virJSONValuePtr actions,
+                                       virHashTablePtr blockNamedNodeData)
+{
+    qemuBlockNamedNodeDataPtr entry;
+    size_t i;
+
+    if (!(entry = virHashLookup(blockNamedNodeData, dd->disk->src->nodeformat)))
+        return 0;
+
+    for (i = 0; i < entry->nbitmaps; i++) {
+        qemuBlockNamedNodeDataBitmapPtr bitmap = entry->bitmaps[i];
+
+        /* we don't care about temporary, inconsistent, or disabled bitmaps */
+        if (!bitmap->persistent || !bitmap->recording || bitmap->inconsistent)
+            continue;
+
+        if (qemuMonitorTransactionBitmapAdd(actions, dd->src->nodeformat,
+                                            bitmap->name, true, false,
+                                            bitmap->granularity) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
 static int
 qemuDomainSnapshotDiskPrepareOneBlockdev(virQEMUDriverPtr driver,
                                          virDomainObjPtr vm,
@@ -15423,6 +15461,9 @@ qemuDomainSnapshotDiskPrepareOne(virQEMUDriverPtr driver,
                                                      blockNamedNodeData, asyncJob) < 0)
             return -1;
 
+        if (qemuDomainSnapshotDiskBitmapsPropagate(dd, actions, blockNamedNodeData) < 0)
+            return -1;
+
         if (qemuBlockSnapshotAddBlockdev(actions, dd->disk, dd->src) < 0)
             return -1;
     } else {