Deleting a snapshot and all its descendants had problems with
tracking the current snapshot. The deletion does not necessarily
proceed in depth-first order, so a parent could be deleted
before a child, wreaking havoc on passing the notion of the
current snapshot to the parent. Furthermore, even if traversal
were depth-first, doing multiple file writes to pass current up
the chain one snapshot at a time is wasteful, comparing to a
single update to the current snapshot at the end of the algorithm.
* src/qemu/qemu_driver.c (snap_remove): Add field.
(qemuDomainSnapshotDiscard): Add parameter.
(qemuDomainSnapshotDiscardDescendant): Adjust accordingly.
(qemuDomainSnapshotDelete): Properly reset current.
---
src/qemu/qemu_driver.c | 20 ++++++++++++++------
1 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 242708c..a96ec84 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9166,9 +9166,11 @@ cleanup:
return ret;
}
-static int qemuDomainSnapshotDiscard(struct qemud_driver *driver,
- virDomainObjPtr vm,
- virDomainSnapshotObjPtr snap)
+static int
+qemuDomainSnapshotDiscard(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainSnapshotObjPtr snap,
+ bool update_current)
{
const char *qemuimgarg[] = { NULL, "snapshot", "-d", NULL, NULL,
NULL };
char *snapFile = NULL;
@@ -9221,7 +9223,7 @@ static int qemuDomainSnapshotDiscard(struct qemud_driver *driver,
}
if (snap == vm->current_snapshot) {
- if (snap->def->parent) {
+ if (update_current && snap->def->parent) {
parentsnap = virDomainSnapshotFindByName(&vm->snapshots,
snap->def->parent);
if (!parentsnap) {
@@ -9258,6 +9260,7 @@ struct snap_remove {
struct qemud_driver *driver;
virDomainObjPtr vm;
int err;
+ bool current;
};
static void
@@ -9269,7 +9272,9 @@ qemuDomainSnapshotDiscardDescendant(void *payload,
struct snap_remove *curr = data;
int err;
- err = qemuDomainSnapshotDiscard(curr->driver, curr->vm, snap);
+ if (snap->def->current)
+ curr->current = true;
+ err = qemuDomainSnapshotDiscard(curr->driver, curr->vm, snap, false);
if (err && !curr->err)
curr->err = err;
}
@@ -9348,12 +9353,15 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr
snapshot,
rem.driver = driver;
rem.vm = vm;
rem.err = 0;
+ rem.current = false;
virDomainSnapshotForEachDescendant(&vm->snapshots,
snap,
qemuDomainSnapshotDiscardDescendant,
&rem);
if (rem.err < 0)
goto endjob;
+ if (rem.current)
+ vm->current_snapshot = snap;
} else {
rep.driver = driver;
rep.snap = snap;
@@ -9365,7 +9373,7 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
goto endjob;
}
- ret = qemuDomainSnapshotDiscard(driver, vm, snap);
+ ret = qemuDomainSnapshotDiscard(driver, vm, snap, true);
endjob:
if (qemuDomainObjEndJob(driver, vm) == 0)
--
1.7.4.4