216 lines
9.0 KiB
Diff
216 lines
9.0 KiB
Diff
From a7a774b357e4f56ef4860dbc04065197e3dd9640 Mon Sep 17 00:00:00 2001
|
|
Message-Id: <a7a774b357e4f56ef4860dbc04065197e3dd9640@dist-git>
|
|
From: Peter Krempa <pkrempa@redhat.com>
|
|
Date: Tue, 4 Feb 2020 15:07:56 +0100
|
|
Subject: [PATCH] qemu: checkpoint: Introduce helper to find checkpoint disk
|
|
definition in parents
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
The algorithm is used in two places to find the parent checkpoint object
|
|
which contains given disk and then uses data from the disk. Additionally
|
|
the code is written in a very non-obvious way. Factor out the lookup of
|
|
the disk into a function which also simplifies the callers.
|
|
|
|
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
|
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
(cherry picked from commit 6796194a28bd42bcbb237ffae6faea262fcce660)
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1207659
|
|
Message-Id: <4b9ca38d8272158c6d254cb1d3dad21cc736ad9f.1580824112.git.pkrempa@redhat.com>
|
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
---
|
|
src/qemu/qemu_checkpoint.c | 127 ++++++++++++++++++++-----------------
|
|
1 file changed, 70 insertions(+), 57 deletions(-)
|
|
|
|
diff --git a/src/qemu/qemu_checkpoint.c b/src/qemu/qemu_checkpoint.c
|
|
index 326707e098..1100f6e744 100644
|
|
--- a/src/qemu/qemu_checkpoint.c
|
|
+++ b/src/qemu/qemu_checkpoint.c
|
|
@@ -104,6 +104,50 @@ qemuCheckpointWriteMetadata(virDomainObjPtr vm,
|
|
}
|
|
|
|
|
|
+/**
|
|
+ * qemuCheckpointFindActiveDiskInParent:
|
|
+ * @vm: domain object
|
|
+ * @from: starting moment object
|
|
+ * @diskname: name (target) of the disk to find
|
|
+ *
|
|
+ * Find the first checkpoint starting from @from continuing through parents
|
|
+ * of the checkpoint which describes disk @diskname. Return the pointer to the
|
|
+ * definition of the disk.
|
|
+ */
|
|
+static virDomainCheckpointDiskDef *
|
|
+qemuCheckpointFindActiveDiskInParent(virDomainObjPtr vm,
|
|
+ virDomainMomentObjPtr from,
|
|
+ const char *diskname)
|
|
+{
|
|
+ virDomainMomentObjPtr parent = from;
|
|
+ virDomainCheckpointDefPtr parentdef = NULL;
|
|
+ size_t i;
|
|
+
|
|
+ while (parent) {
|
|
+ parentdef = virDomainCheckpointObjGetDef(parent);
|
|
+
|
|
+ for (i = 0; i < parentdef->ndisks; i++) {
|
|
+ virDomainCheckpointDiskDef *chkdisk = &parentdef->disks[i];
|
|
+
|
|
+ if (STRNEQ(chkdisk->name, diskname))
|
|
+ continue;
|
|
+
|
|
+ /* currently inspected checkpoint doesn't describe the disk,
|
|
+ * continue into parent checkpoint */
|
|
+ if (chkdisk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
|
|
+ break;
|
|
+
|
|
+ return chkdisk;
|
|
+ }
|
|
+
|
|
+ parent = virDomainCheckpointFindByName(vm->checkpoints,
|
|
+ parentdef->parent.parent_name);
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+
|
|
static int
|
|
qemuCheckpointDiscardBitmaps(virDomainObjPtr vm,
|
|
virDomainCheckpointDefPtr chkdef,
|
|
@@ -112,13 +156,9 @@ qemuCheckpointDiscardBitmaps(virDomainObjPtr vm,
|
|
{
|
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
virQEMUDriverPtr driver = priv->driver;
|
|
- virDomainMomentObjPtr moment;
|
|
- virDomainCheckpointDefPtr parentdef = NULL;
|
|
- bool search_parents;
|
|
int rc;
|
|
g_autoptr(virJSONValue) actions = NULL;
|
|
size_t i;
|
|
- size_t j;
|
|
|
|
if (!(actions = virJSONValueNewArray()))
|
|
return -1;
|
|
@@ -126,6 +166,7 @@ qemuCheckpointDiscardBitmaps(virDomainObjPtr vm,
|
|
for (i = 0; i < chkdef->ndisks; i++) {
|
|
virDomainCheckpointDiskDef *chkdisk = &chkdef->disks[i];
|
|
virDomainDiskDefPtr domdisk = virDomainDiskByTarget(vm->def, chkdisk->name);
|
|
+ virDomainCheckpointDiskDef *parentchkdisk = NULL;
|
|
|
|
/* domdisk can be missing e.g. when it was unplugged */
|
|
if (!domdisk)
|
|
@@ -137,42 +178,28 @@ qemuCheckpointDiscardBitmaps(virDomainObjPtr vm,
|
|
/* If any ancestor checkpoint has a bitmap for the same
|
|
* disk, then this bitmap must be merged to the
|
|
* ancestor. */
|
|
- search_parents = true;
|
|
- for (moment = parent;
|
|
- search_parents && moment;
|
|
- moment = virDomainCheckpointFindByName(vm->checkpoints,
|
|
- parentdef->parent.parent_name)) {
|
|
- parentdef = virDomainCheckpointObjGetDef(moment);
|
|
- for (j = 0; j < parentdef->ndisks; j++) {
|
|
- virDomainCheckpointDiskDef *disk2;
|
|
- g_autoptr(virJSONValue) arr = NULL;
|
|
+ if ((parentchkdisk = qemuCheckpointFindActiveDiskInParent(vm, parent, chkdisk->name))) {
|
|
+ g_autoptr(virJSONValue) arr = NULL;
|
|
|
|
- disk2 = &parentdef->disks[j];
|
|
- if (STRNEQ(chkdisk->name, disk2->name) ||
|
|
- disk2->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
|
|
- continue;
|
|
- search_parents = false;
|
|
+ if (!(arr = virJSONValueNewArray()))
|
|
+ return -1;
|
|
|
|
- if (!(arr = virJSONValueNewArray()))
|
|
- return -1;
|
|
+ if (qemuMonitorTransactionBitmapMergeSourceAddBitmap(arr,
|
|
+ domdisk->src->nodeformat,
|
|
+ chkdisk->bitmap) < 0)
|
|
+ return -1;
|
|
|
|
- if (qemuMonitorTransactionBitmapMergeSourceAddBitmap(arr,
|
|
- domdisk->src->nodeformat,
|
|
- chkdisk->bitmap) < 0)
|
|
- return -1;
|
|
-
|
|
- if (chkcurrent) {
|
|
- if (qemuMonitorTransactionBitmapEnable(actions,
|
|
- domdisk->src->nodeformat,
|
|
- disk2->bitmap) < 0)
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if (qemuMonitorTransactionBitmapMerge(actions,
|
|
- domdisk->src->nodeformat,
|
|
- disk2->bitmap, &arr) < 0)
|
|
+ if (chkcurrent) {
|
|
+ if (qemuMonitorTransactionBitmapEnable(actions,
|
|
+ domdisk->src->nodeformat,
|
|
+ parentchkdisk->bitmap) < 0)
|
|
return -1;
|
|
}
|
|
+
|
|
+ if (qemuMonitorTransactionBitmapMerge(actions,
|
|
+ domdisk->src->nodeformat,
|
|
+ parentchkdisk->bitmap, &arr) < 0)
|
|
+ return -1;
|
|
}
|
|
|
|
if (qemuMonitorTransactionBitmapRemove(actions,
|
|
@@ -324,14 +351,12 @@ qemuCheckpointAddActions(virDomainObjPtr vm,
|
|
virDomainMomentObjPtr old_current,
|
|
virDomainCheckpointDefPtr def)
|
|
{
|
|
- size_t i, j;
|
|
- virDomainCheckpointDefPtr olddef;
|
|
- virDomainMomentObjPtr parent;
|
|
- bool search_parents;
|
|
+ size_t i;
|
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
|
virDomainCheckpointDiskDef *chkdisk = &def->disks[i];
|
|
virDomainDiskDefPtr domdisk = virDomainDiskByTarget(vm->def, chkdisk->name);
|
|
+ virDomainCheckpointDiskDef *parentchkdisk = NULL;
|
|
|
|
/* checkpoint definition validator mandates that the corresponding
|
|
* domdisk should exist */
|
|
@@ -351,25 +376,13 @@ qemuCheckpointAddActions(virDomainObjPtr vm,
|
|
* iteration; but it is also possible to have to search
|
|
* further than the immediate parent to find another
|
|
* checkpoint with a bitmap on the same disk. */
|
|
- search_parents = true;
|
|
- for (parent = old_current; search_parents && parent;
|
|
- parent = virDomainCheckpointFindByName(vm->checkpoints,
|
|
- olddef->parent.parent_name)) {
|
|
- olddef = virDomainCheckpointObjGetDef(parent);
|
|
- for (j = 0; j < olddef->ndisks; j++) {
|
|
- virDomainCheckpointDiskDef *disk2;
|
|
+ if ((parentchkdisk = qemuCheckpointFindActiveDiskInParent(vm, old_current,
|
|
+ chkdisk->name))) {
|
|
|
|
- disk2 = &olddef->disks[j];
|
|
- if (STRNEQ(chkdisk->name, disk2->name) ||
|
|
- disk2->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
|
|
- continue;
|
|
- if (qemuMonitorTransactionBitmapDisable(actions,
|
|
- domdisk->src->nodeformat,
|
|
- disk2->bitmap) < 0)
|
|
- return -1;
|
|
- search_parents = false;
|
|
- break;
|
|
- }
|
|
+ if (qemuMonitorTransactionBitmapDisable(actions,
|
|
+ domdisk->src->nodeformat,
|
|
+ parentchkdisk->bitmap) < 0)
|
|
+ return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
--
|
|
2.25.0
|
|
|