]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: snapshot: delete disk image only if parent snapshot is external
authorPavel Hrdina <phrdina@redhat.com>
Thu, 9 Jan 2025 15:23:44 +0000 (16:23 +0100)
committerPavel Hrdina <phrdina@redhat.com>
Fri, 10 Jan 2025 17:57:16 +0000 (18:57 +0100)
When we are deleting external snapshot that is not active we only need
to delete overlay disk image of the parent snapshot. This works
correctly even if parent snapshot is external and active as it will have
another overlay created when user reverted to that snapshot.

In case the parent snapshot is internal there are no overlay disk images
created as everything is stored internally within the disk image. In
this case we would delete the actual disk image storing internal
snapshots and most likely the original disk image as well resulting in
data loss once the VM is shutoff.

Fixes: https://gitlab.com/libvirt/libvirt/-/issues/734
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
src/qemu/qemu_snapshot.c

index 18b2e478f6457dbfa3611a3eba59aa4962063f22..80cd54bf3360bb6e06a463df289f48f90eb8609d 100644 (file)
@@ -3144,6 +3144,8 @@ qemuSnapshotDeleteExternalPrepareData(virDomainObj *vm,
             return -1;
         }
 
+        data->parentSnap = qemuSnapshotFindParentSnapForDisk(snap, data->snapDisk);
+
         if (data->merge) {
             virStorageSource *snapDiskSrc = NULL;
 
@@ -3185,8 +3187,6 @@ qemuSnapshotDeleteExternalPrepareData(virDomainObj *vm,
                 qemuSnapshotGetDisksWithBackingStore(vm, snap, data);
             }
 
-            data->parentSnap = qemuSnapshotFindParentSnapForDisk(snap, data->snapDisk);
-
             if (data->parentSnap && !virDomainSnapshotIsExternal(data->parentSnap)) {
                 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                                _("deleting external snapshot that has internal snapshot as parent not supported"));
@@ -3642,10 +3642,12 @@ qemuSnapshotDiscardExternal(virDomainObj *vm,
             if (!data->job)
                 goto error;
         } else {
-            if (virStorageSourceInit(data->parentDomDisk->src) < 0 ||
-                virStorageSourceUnlink(data->parentDomDisk->src) < 0) {
-                VIR_WARN("Failed to remove snapshot image '%s'",
-                         data->snapDisk->name);
+            if (data->parentSnap && virDomainSnapshotIsExternal(data->parentSnap)) {
+                if (virStorageSourceInit(data->parentDomDisk->src) < 0 ||
+                    virStorageSourceUnlink(data->parentDomDisk->src) < 0) {
+                    VIR_WARN("Failed to remove snapshot image '%s'",
+                             data->snapDisk->name);
+                }
             }
         }
     }