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