]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu_snapshot: refactor validation of snapshot delete
authorPavel Hrdina <phrdina@redhat.com>
Tue, 23 Aug 2022 11:18:35 +0000 (13:18 +0200)
committerPavel Hrdina <phrdina@redhat.com>
Mon, 9 Jan 2023 12:32:59 +0000 (13:32 +0100)
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@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
src/qemu/qemu_snapshot.c

index 2e0e4896f5a6aab71f4d9094399f52283b8228a3..c23f629e9fde84382232edbdaad13dde7af2ae46 100644 (file)
@@ -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,
@@ -2482,26 +2467,60 @@ 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++;
 
     if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
-                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY))
+                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
+        qemuSnapshotCount count = { 0 };
+
         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;
     }