From: Peter Krempa Date: Thu, 28 Nov 2019 15:06:31 +0000 (+0100) Subject: qemu: snapshot: Propagate active bitmaps through external snapshots X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=3283445212708d432737650cf967b53e7aa58926;p=libvirt.git qemu: snapshot: Propagate active bitmaps through external snapshots 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 Reviewed-by: Eric Blake --- diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index aa920c1edd..accffef168 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -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 {