From eee9a7173898212632d42ef74777d6726ce29d5f Mon Sep 17 00:00:00 2001
Message-Id: <eee9a7173898212632d42ef74777d6726ce29d5f@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 4 Feb 2020 15:08:15 +0100
Subject: [PATCH] qemu: checkpoint: Track and relabel images for bitmap merging
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Allow qemu access to modify backing files in case when we want to delete
a checkpoint.
This patch adds tracking of which images need to be relabelled when
calculating the transaction, the code to relabel them and rollback.
To verify that stuff works we also output the list of images to relabel
into the test case output files in qemublocktest.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit 8e94e290104ffb5d9db051ab0b0ff36f58dbc943)
https://bugzilla.redhat.com/show_bug.cgi?id=1207659
Message-Id: <36c2dc7f5d0d59aac90b2e272983f72476b00661.1580824112.git.pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
---
src/qemu/qemu_checkpoint.c | 35 ++++++++++++++++---
src/qemu/qemu_checkpoint.h | 3 +-
tests/qemublocktest.c | 19 ++++++++--
.../snapshots-intermediate1-out.json | 2 ++
.../snapshots-intermediate2-out.json | 3 ++
.../snapshots-intermediate3-out.json | 2 ++
.../snapshots-noparent-out.json | 4 +++
...ynthetic-checkpoint-intermediate1-out.json | 2 ++
...ynthetic-checkpoint-intermediate2-out.json | 2 ++
...ynthetic-checkpoint-intermediate3-out.json | 2 ++
...ots-synthetic-checkpoint-noparent-out.json | 4 +++
11 files changed, 70 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_checkpoint.c b/src/qemu/qemu_checkpoint.c
index 55061bbf76..59b7f63fdc 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 976b1eed0f..cf1e9e46cb 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 2e5927f3c1..ed8b061e2e 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -717,6 +717,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);
@@ -738,14 +741,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 29fefeea63..c9bda3a17a 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 4da21a9df7..8a0e3f2cff 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 dc87dd60b8..211bc40baf 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 45a84b47c2..f750f44da2 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 e979691e6f..d7e6d18637 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 e82098918a..cfbff010c2 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 dc87dd60b8..211bc40baf 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 45a84b47c2..f750f44da2 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
--
2.25.0