diff --git a/src/qemu/qemu_checkpoint.c b/src/qemu/qemu_checkpoint.c index 55061bbf7653185e847e9c364cace6eae4b380d7..59b7f63fdc2582354d264620a1cdaf42a2c6d1e7 100644 --- a/src/qemu/qemu_checkpoint.c +++ b/src/qemu/qemu_checkpoint.c @@ -155,7 +155,8 @@ qemuCheckpointDiscardDiskBitmaps(virStorageSourcePtr src, const char *delbitmap, const char *parentbitmap, virJSONValuePtr actions, - const char *diskdst) + const char *diskdst, + GSList **reopenimages) { virStorageSourcePtr n = src; @@ -235,6 +236,9 @@ qemuCheckpointDiscardDiskBitmaps(virStorageSourcePtr src, srcbitmap->name) < 0) return -1; + if (n != src) + *reopenimages = g_slist_prepend(*reopenimages, n); + n = n->backingStore; } @@ -250,9 +254,12 @@ qemuCheckpointDiscardBitmaps(virDomainObjPtr vm, qemuDomainObjPrivatePtr priv = vm->privateData; virQEMUDriverPtr driver = priv->driver; g_autoptr(virHashTable) blockNamedNodeData = NULL; - int rc; + int rc = -1; g_autoptr(virJSONValue) actions = NULL; size_t i; + g_autoptr(GSList) reopenimages = NULL; + g_autoptr(GSList) relabelimages = NULL; + GSList *next; if (!(actions = virJSONValueNewArray())) return -1; @@ -284,16 +291,34 @@ qemuCheckpointDiscardBitmaps(virDomainObjPtr vm, if (qemuCheckpointDiscardDiskBitmaps(domdisk->src, blockNamedNodeData, chkdisk->bitmap, parentbitmap, - actions, domdisk->dst) < 0) + actions, domdisk->dst, + &reopenimages) < 0) return -1; } + /* label any non-top images for read-write access */ + for (next = reopenimages; next; next = next->next) { + virStorageSourcePtr src = next->data; + + if (qemuDomainStorageSourceAccessAllow(driver, vm, src, false, false) < 0) + goto relabel; + + relabelimages = g_slist_prepend(relabelimages, src); + } + qemuDomainObjEnterMonitor(driver, vm); rc = qemuMonitorTransaction(priv->mon, &actions); - if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0) + if (qemuDomainObjExitMonitor(driver, vm) < 0) return -1; - return 0; + relabel: + for (next = relabelimages; next; next = next->next) { + virStorageSourcePtr src = next->data; + + ignore_value(qemuDomainStorageSourceAccessAllow(driver, vm, src, true, false)); + } + + return rc; } diff --git a/src/qemu/qemu_checkpoint.h b/src/qemu/qemu_checkpoint.h index 976b1eed0f6d22f58836819a66166eed0344a2d5..cf1e9e46cb25093f5ab935921ef2b3f0c6e2751a 100644 --- a/src/qemu/qemu_checkpoint.h +++ b/src/qemu/qemu_checkpoint.h @@ -78,4 +78,5 @@ qemuCheckpointDiscardDiskBitmaps(virStorageSourcePtr src, const char *delbitmap, const char *parentbitmap, virJSONValuePtr actions, - const char *diskdst); + const char *diskdst, + GSList **reopenimages); diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 8f290452062ff81c7959506eed397a61e7c95f91..f518b0e025353780ad4a34a2b2aa4fb133fde7a7 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -721,6 +721,9 @@ testQemuCheckpointDeleteMerge(const void *opaque) g_autoptr(virJSONValue) actions = NULL; g_autoptr(virJSONValue) nodedatajson = NULL; g_autoptr(virHashTable) nodedata = NULL; + g_autoptr(GSList) reopenimages = NULL; + g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; + GSList *tmp; expectpath = g_strdup_printf("%s/%s%s-out.json", abs_srcdir, checkpointDeletePrefix, data->name); @@ -742,14 +745,26 @@ testQemuCheckpointDeleteMerge(const void *opaque) data->deletebitmap, data->parentbitmap, actions, - "testdisk") < 0) { + "testdisk", + &reopenimages) < 0) { VIR_TEST_VERBOSE("failed to generate checkpoint delete transaction\n"); return -1; } - if (!(actual = virJSONValueToString(actions, true))) + if (virJSONValueToBuffer(actions, &buf, true) < 0) return -1; + if (reopenimages) { + virBufferAddLit(&buf, "reopen nodes:\n"); + + for (tmp = reopenimages; tmp; tmp = tmp->next) { + virStorageSourcePtr src = tmp->data; + virBufferAsprintf(&buf, "%s\n", src->nodeformat); + } + } + + actual = virBufferContentAndReset(&buf); + return virTestCompareToFile(actual, expectpath); } diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json index 29fefeea6301756cbcd05437a5944e9490229225..c9bda3a17a9e40e222c523cc81260fa94c402b7e 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json @@ -20,3 +20,5 @@ } } ] +reopen nodes: +libvirt-3-format diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json index 4da21a9df71230df76d7b6a0e8e6963f7a310d1f..8a0e3f2cff8d9bbc050f026698c2671c26d227ad 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json @@ -57,3 +57,6 @@ } } ] +reopen nodes: +libvirt-3-format +libvirt-2-format diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json index dc87dd60b87335a19cf6a9f1be590877f75da4be..211bc40bafbd2ebf9325eaf48198f0142278b469 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json @@ -57,3 +57,5 @@ } } ] +reopen nodes: +libvirt-2-format diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json index 45a84b47c24ca7cde95f72acb0ecdaf8008cfa8e..f750f44da2029eac82d3deb1936b1ab2b0fbb84f 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json @@ -21,3 +21,7 @@ } } ] +reopen nodes: +libvirt-5-format +libvirt-4-format +libvirt-3-format diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json index e979691e6fc1661c34babbbd4d37660ee3d68ea0..d7e6d1863742f2d70582c9bdd0ef6fd96f240338 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json @@ -27,3 +27,5 @@ } } ] +reopen nodes: +libvirt-3-format diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json index e82098918aeece855289b7f47901ac75ab18517d..cfbff010c2c6ddfa051a4e72fe8147b16fd52d3d 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json @@ -30,3 +30,5 @@ } } ] +reopen nodes: +libvirt-2-format diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json index dc87dd60b87335a19cf6a9f1be590877f75da4be..211bc40bafbd2ebf9325eaf48198f0142278b469 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json @@ -57,3 +57,5 @@ } } ] +reopen nodes: +libvirt-2-format diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json index 45a84b47c24ca7cde95f72acb0ecdaf8008cfa8e..f750f44da2029eac82d3deb1936b1ab2b0fbb84f 100644 --- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json +++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json @@ -21,3 +21,7 @@ } } ] +reopen nodes: +libvirt-5-format +libvirt-4-format +libvirt-3-format