Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_checkpoint.c | 185 ++++++++++++++++++++++++++++++++++---
src/qemu/qemu_checkpoint.h | 5 +
src/qemu/qemu_domain.c | 162 +-------------------------------
src/qemu/qemu_domain.h | 15 ---
4 files changed, 180 insertions(+), 187 deletions(-)
diff --git a/src/qemu/qemu_checkpoint.c b/src/qemu/qemu_checkpoint.c
index 9e9af76871..22f0ffb26e 100644
--- a/src/qemu/qemu_checkpoint.c
+++ b/src/qemu/qemu_checkpoint.c
@@ -76,6 +76,169 @@ qemuCheckpointObjFromCheckpoint(virDomainObjPtr vm,
}
+static int
+qemuCheckpointWriteMetadata(virDomainObjPtr vm,
+ virDomainMomentObjPtr checkpoint,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ const char *checkpointDir)
+{
+ unsigned int flags = VIR_DOMAIN_CHECKPOINT_FORMAT_SECURE;
+ virDomainCheckpointDefPtr def = virDomainCheckpointObjGetDef(checkpoint);
+ VIR_AUTOFREE(char *) newxml = NULL;
+ VIR_AUTOFREE(char *) chkDir = NULL;
+ VIR_AUTOFREE(char *) chkFile = NULL;
+
+ newxml = virDomainCheckpointDefFormat(def, caps, xmlopt, flags);
+ if (newxml == NULL)
+ return -1;
+
+ if (virAsprintf(&chkDir, "%s/%s", checkpointDir, vm->def->name)
< 0)
+ return -1;
+ if (virFileMakePath(chkDir) < 0) {
+ virReportSystemError(errno, _("cannot create checkpoint directory
'%s'"),
+ chkDir);
+ return -1;
+ }
+
+ if (virAsprintf(&chkFile, "%s/%s.xml", chkDir, def->parent.name)
< 0)
+ return -1;
+
+ return virXMLSaveFile(chkFile, NULL, "checkpoint-edit", newxml);
+}
+
+
+static int
+qemuDomainCheckpointDiscard(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainMomentObjPtr chk,
+ bool update_parent,
+ bool metadata_only)
+{
+ virDomainMomentObjPtr parent = NULL;
+ virDomainMomentObjPtr moment;
+ virDomainCheckpointDefPtr parentdef = NULL;
+ size_t i, j;
+ VIR_AUTOUNREF(virQEMUDriverConfigPtr) cfg = virQEMUDriverGetConfig(driver);
+ VIR_AUTOFREE(char *) chkFile = NULL;
+
+ if (!metadata_only && !virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("cannot remove checkpoint from inactive domain"));
+ return -1;
+ }
+
+ if (virAsprintf(&chkFile, "%s/%s/%s.xml", cfg->checkpointDir,
+ vm->def->name, chk->def->name) < 0)
+ return -1;
+
+ if (!metadata_only) {
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ bool success = true;
+ bool search_parents;
+ virDomainCheckpointDefPtr chkdef = virDomainCheckpointObjGetDef(chk);
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ parent = virDomainCheckpointFindByName(vm->checkpoints,
+ chk->def->parent_name);
+ for (i = 0; i < chkdef->ndisks; i++) {
+ virDomainCheckpointDiskDef *disk = &chkdef->disks[i];
+ const char *node;
+
+ if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
+ continue;
+
+ node = qemuDomainDiskNodeFormatLookup(vm, disk->name);
+ /* 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;
+ VIR_AUTOPTR(virJSONValue) arr = NULL;
+
+ disk2 = &parentdef->disks[j];
+ if (STRNEQ(disk->name, disk2->name) ||
+ disk2->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
+ continue;
+ search_parents = false;
+
+ arr = virJSONValueNewArray();
+ if (!arr ||
+ virJSONValueArrayAppendString(arr, disk->bitmap) < 0) {
+ success = false;
+ break;
+ }
+ if (chk == virDomainCheckpointGetCurrent(vm->checkpoints)
&&
+ qemuMonitorEnableBitmap(priv->mon, node,
+ disk2->bitmap) < 0) {
+ success = false;
+ break;
+ }
+ if (qemuMonitorMergeBitmaps(priv->mon, node,
+ disk2->bitmap, &arr) < 0) {
+ success = false;
+ break;
+ }
+ }
+ }
+ if (qemuMonitorDeleteBitmap(priv->mon, node, disk->bitmap) < 0) {
+ success = false;
+ break;
+ }
+ }
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || !success)
+ return -1;
+ }
+
+ if (chk == virDomainCheckpointGetCurrent(vm->checkpoints)) {
+ virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
+ if (update_parent && parent) {
+ virDomainCheckpointSetCurrent(vm->checkpoints, parent);
+ if (qemuCheckpointWriteMetadata(vm, parent, driver->caps,
+ driver->xmlopt,
+ cfg->checkpointDir) < 0) {
+ VIR_WARN("failed to set parent checkpoint '%s' as
current",
+ chk->def->parent_name);
+ virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
+ }
+ }
+ }
+
+ if (unlink(chkFile) < 0)
+ VIR_WARN("Failed to unlink %s", chkFile);
+ if (update_parent)
+ virDomainMomentDropParent(chk);
+ virDomainCheckpointObjListRemove(vm->checkpoints, chk);
+
+ return 0;
+}
+
+
+int
+qemuDomainCheckpointDiscardAllMetadata(virQEMUDriverPtr driver,
+ virDomainObjPtr vm)
+{
+ virQEMUMomentRemove rem = {
+ .driver = driver,
+ .vm = vm,
+ .metadata_only = true,
+ .momentDiscard = qemuDomainCheckpointDiscard,
+ };
+
+ virDomainCheckpointForEach(vm->checkpoints, qemuDomainMomentDiscardAll,
+ &rem);
+ virDomainCheckpointObjListRemoveAll(vm->checkpoints);
+
+ return rem.err;
+}
+
+
/* Called inside job lock */
static int
qemuDomainCheckpointPrepare(virQEMUDriverPtr driver, virCapsPtr caps,
@@ -267,9 +430,9 @@ qemuCheckpointCreateXML(virDomainPtr domain,
goto endjob;
if (update_current) {
virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
- if (qemuDomainCheckpointWriteMetadata(vm, other,
- driver->caps, driver->xmlopt,
- cfg->checkpointDir) < 0)
+ if (qemuCheckpointWriteMetadata(vm, other,
+ driver->caps, driver->xmlopt,
+ cfg->checkpointDir) < 0)
goto endjob;
}
}
@@ -301,9 +464,9 @@ qemuCheckpointCreateXML(virDomainPtr domain,
if (checkpoint) {
if (update_current)
virDomainCheckpointSetCurrent(vm->checkpoints, chk);
- if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
- driver->xmlopt,
- cfg->checkpointDir) < 0) {
+ if (qemuCheckpointWriteMetadata(vm, chk, driver->caps,
+ driver->xmlopt,
+ cfg->checkpointDir) < 0) {
/* if writing of metadata fails, error out rather than trying
* to silently carry on without completing the checkpoint */
virObjectUnref(checkpoint);
@@ -384,8 +547,8 @@ qemuCheckpointReparentChildren(void *payload,
return 0;
}
- rep->err = qemuDomainCheckpointWriteMetadata(rep->vm, moment, rep->caps,
- rep->xmlopt, rep->dir);
+ rep->err = qemuCheckpointWriteMetadata(rep->vm, moment, rep->caps,
+ rep->xmlopt, rep->dir);
return 0;
}
@@ -445,9 +608,9 @@ qemuCheckpointDelete(virDomainObjPtr vm,
if (rem.found) {
virDomainCheckpointSetCurrent(vm->checkpoints, chk);
if (flags & VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY) {
- if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
- driver->xmlopt,
- cfg->checkpointDir) < 0) {
+ if (qemuCheckpointWriteMetadata(vm, chk, driver->caps,
+ driver->xmlopt,
+ cfg->checkpointDir) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("failed to set checkpoint '%s' as
current"),
chk->def->name);
diff --git a/src/qemu/qemu_checkpoint.h b/src/qemu/qemu_checkpoint.h
index 0d36d718d6..4cea4bcdb4 100644
--- a/src/qemu/qemu_checkpoint.h
+++ b/src/qemu/qemu_checkpoint.h
@@ -20,6 +20,7 @@
#include "virconftypes.h"
#include "datatypes.h"
+#include "qemu_conf.h"
virDomainObjPtr
qemuDomObjFromCheckpoint(virDomainCheckpointPtr checkpoint);
@@ -32,6 +33,10 @@ virDomainMomentObjPtr
qemuCheckpointObjFromName(virDomainObjPtr vm,
const char *name);
+int
+qemuDomainCheckpointDiscardAllMetadata(virQEMUDriverPtr driver,
+ virDomainObjPtr vm);
+
virDomainCheckpointPtr
qemuCheckpointCreateXML(virDomainPtr domain,
virDomainObjPtr vm,
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index e8e895d9aa..19fa5420e7 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -35,6 +35,7 @@
#include "qemu_slirp.h"
#include "qemu_extdevice.h"
#include "qemu_blockjob.h"
+#include "qemu_checkpoint.h"
#include "viralloc.h"
#include "virlog.h"
#include "virerror.h"
@@ -9600,36 +9601,6 @@ qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
return ret;
}
-int
-qemuDomainCheckpointWriteMetadata(virDomainObjPtr vm,
- virDomainMomentObjPtr checkpoint,
- virCapsPtr caps,
- virDomainXMLOptionPtr xmlopt,
- const char *checkpointDir)
-{
- unsigned int flags = VIR_DOMAIN_CHECKPOINT_FORMAT_SECURE;
- virDomainCheckpointDefPtr def = virDomainCheckpointObjGetDef(checkpoint);
- VIR_AUTOFREE(char *) newxml = NULL;
- VIR_AUTOFREE(char *) chkDir = NULL;
- VIR_AUTOFREE(char *) chkFile = NULL;
-
- newxml = virDomainCheckpointDefFormat(def, caps, xmlopt, flags);
- if (newxml == NULL)
- return -1;
-
- if (virAsprintf(&chkDir, "%s/%s", checkpointDir, vm->def->name)
< 0)
- return -1;
- if (virFileMakePath(chkDir) < 0) {
- virReportSystemError(errno, _("cannot create checkpoint directory
'%s'"),
- chkDir);
- return -1;
- }
-
- if (virAsprintf(&chkFile, "%s/%s.xml", chkDir, def->parent.name)
< 0)
- return -1;
-
- return virXMLSaveFile(chkFile, NULL, "checkpoint-edit", newxml);
-}
/* The domain is expected to be locked and inactive. Return -1 on normal
* failure, 1 if we skipped a disk due to try_all. */
@@ -9827,137 +9798,6 @@ qemuDomainSnapshotDiscardAllMetadata(virQEMUDriverPtr driver,
}
-/* Discard one checkpoint (or its metadata), without reparenting any children. */
-int
-qemuDomainCheckpointDiscard(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- virDomainMomentObjPtr chk,
- bool update_parent,
- bool metadata_only)
-{
- virDomainMomentObjPtr parent = NULL;
- virDomainMomentObjPtr moment;
- virDomainCheckpointDefPtr parentdef = NULL;
- size_t i, j;
- VIR_AUTOUNREF(virQEMUDriverConfigPtr) cfg = virQEMUDriverGetConfig(driver);
- VIR_AUTOFREE(char *) chkFile = NULL;
-
- if (!metadata_only && !virDomainObjIsActive(vm)) {
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("cannot remove checkpoint from inactive domain"));
- return -1;
- }
-
- if (virAsprintf(&chkFile, "%s/%s/%s.xml", cfg->checkpointDir,
- vm->def->name, chk->def->name) < 0)
- return -1;
-
- if (!metadata_only) {
- qemuDomainObjPrivatePtr priv = vm->privateData;
- bool success = true;
- bool search_parents;
- virDomainCheckpointDefPtr chkdef = virDomainCheckpointObjGetDef(chk);
-
- qemuDomainObjEnterMonitor(driver, vm);
- parent = virDomainCheckpointFindByName(vm->checkpoints,
- chk->def->parent_name);
- for (i = 0; i < chkdef->ndisks; i++) {
- virDomainCheckpointDiskDef *disk = &chkdef->disks[i];
- const char *node;
-
- if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
- continue;
-
- node = qemuDomainDiskNodeFormatLookup(vm, disk->name);
- /* 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;
- VIR_AUTOPTR(virJSONValue) arr = NULL;
-
- disk2 = &parentdef->disks[j];
- if (STRNEQ(disk->name, disk2->name) ||
- disk2->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
- continue;
- search_parents = false;
-
- arr = virJSONValueNewArray();
- if (!arr ||
- virJSONValueArrayAppendString(arr, disk->bitmap) < 0) {
- success = false;
- break;
- }
- if (chk == virDomainCheckpointGetCurrent(vm->checkpoints)
&&
- qemuMonitorEnableBitmap(priv->mon, node,
- disk2->bitmap) < 0) {
- success = false;
- break;
- }
- if (qemuMonitorMergeBitmaps(priv->mon, node,
- disk2->bitmap, &arr) < 0) {
- success = false;
- break;
- }
- }
- }
- if (qemuMonitorDeleteBitmap(priv->mon, node, disk->bitmap) < 0) {
- success = false;
- break;
- }
- }
- if (qemuDomainObjExitMonitor(driver, vm) < 0 || !success)
- return -1;
- }
-
- if (chk == virDomainCheckpointGetCurrent(vm->checkpoints)) {
- virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
- if (update_parent && parent) {
- virDomainCheckpointSetCurrent(vm->checkpoints, parent);
- if (qemuDomainCheckpointWriteMetadata(vm, parent, driver->caps,
- driver->xmlopt,
- cfg->checkpointDir) < 0) {
- VIR_WARN("failed to set parent checkpoint '%s' as
current",
- chk->def->parent_name);
- virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
- }
- }
- }
-
- if (unlink(chkFile) < 0)
- VIR_WARN("Failed to unlink %s", chkFile);
- if (update_parent)
- virDomainMomentDropParent(chk);
- virDomainCheckpointObjListRemove(vm->checkpoints, chk);
-
- return 0;
-}
-
-int
-qemuDomainCheckpointDiscardAllMetadata(virQEMUDriverPtr driver,
- virDomainObjPtr vm)
-{
- virQEMUMomentRemove rem = {
- .driver = driver,
- .vm = vm,
- .metadata_only = true,
- .momentDiscard = qemuDomainCheckpointDiscard,
- };
-
- virDomainCheckpointForEach(vm->checkpoints, qemuDomainMomentDiscardAll,
- &rem);
- virDomainCheckpointObjListRemoveAll(vm->checkpoints);
-
- return rem.err;
-}
-
-
static void
qemuDomainRemoveInactiveCommon(virQEMUDriverPtr driver,
virDomainObjPtr vm)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index c740bb955a..f45da882a8 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -792,21 +792,6 @@ int qemuDomainMomentDiscardAll(void *payload,
int qemuDomainSnapshotDiscardAllMetadata(virQEMUDriverPtr driver,
virDomainObjPtr vm);
-int qemuDomainCheckpointWriteMetadata(virDomainObjPtr vm,
- virDomainMomentObjPtr checkpoint,
- virCapsPtr caps,
- virDomainXMLOptionPtr xmlopt,
- const char *checkpointDir);
-
-int qemuDomainCheckpointDiscard(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- virDomainMomentObjPtr chk,
- bool update_current,
- bool metadata_only);
-
-int qemuDomainCheckpointDiscardAllMetadata(virQEMUDriverPtr driver,
- virDomainObjPtr vm);
-
void qemuDomainRemoveInactive(virQEMUDriverPtr driver,
virDomainObjPtr vm);
--
2.21.0