[libvirt RFC 19/24] qemu_snapshot: refactor validation of snapshot delete

Pavel Hrdina phrdina at redhat.com
Tue Aug 23 16:32:22 UTC 2022


Prepare the validation function for external snapshot delete support.

There is one exception when deleting `children-only` snapshots. If the
snapshot tree is like this example:

    snap1 (external)
     |
     +- snap2 (internal)
         |
         +- snap3 (internal)
             |
             +- snap4 (internal)

and user calls `snapshot-delete snap1 --children-only` the current
snapshot is external but all the children snapshots are internal only
and we are able to delete it.

Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
---
 src/qemu/qemu_snapshot.c | 72 +++++++++++++++++++++++++---------------
 1 file changed, 45 insertions(+), 27 deletions(-)

diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 42bc410078..da9b4c30f0 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -100,21 +100,6 @@ qemuSnapObjFromSnapshot(virDomainObj *vm,
 }
 
 
-/* Count how many snapshots in a set are external snapshots.  */
-static int
-qemuSnapshotCountExternal(void *payload,
-                          const char *name G_GNUC_UNUSED,
-                          void *data)
-{
-    virDomainMomentObj *snap = payload;
-    int *count = data;
-
-    if (virDomainSnapshotIsExternal(snap))
-        (*count)++;
-    return 0;
-}
-
-
 int
 qemuSnapshotFSFreeze(virDomainObj *vm,
                      const char **mountpoints,
@@ -2469,26 +2454,59 @@ qemuSnapshotDeleteChildren(virDomainObj *vm,
 }
 
 
+typedef struct {
+    int external;
+    int internal;
+} qemuSnapshotCount;
+
+
+static int
+qemuSnapshotCountExternalInternal(void *payload,
+                                  const char *name G_GNUC_UNUSED,
+                                  void *data)
+{
+    virDomainMomentObj *snap = payload;
+    qemuSnapshotCount *count = data;
+
+    if (virDomainSnapshotIsExternal(snap)) {
+        count->external++;
+    } else {
+        count->internal++;
+    }
+
+    return 0;
+}
+
+
 static int
 qemuSnapshotDeleteValidate(virDomainMomentObj *snap,
                            unsigned int flags)
 {
-    int external = 0;
-
-    if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
-        virDomainSnapshotIsExternal(snap))
-        external++;
+    qemuSnapshotCount count = { 0 };
 
     if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
-                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY))
+                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
         virDomainMomentForEachDescendant(snap,
-                                         qemuSnapshotCountExternal,
-                                         &external);
+                                         qemuSnapshotCountExternalInternal,
+                                         &count);
+    }
 
-    if (external) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("deletion of %d external disk snapshots not "
-                         "supported yet"), external);
+    if (count.external > 0 && count.internal > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("deletion of external and internal children disk snapshots not supported"));
+        return -1;
+    }
+
+    if (count.external > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("deletion of external children disk snapshots not supported"));
+        return -1;
+    }
+
+    if (virDomainSnapshotIsExternal(snap) &&
+        !(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("deletion of external disk snapshots not supported"));
         return -1;
     }
 
-- 
2.37.2



More information about the libvir-list mailing list