[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCHv4 37/51] snapshot: introduce new deletion flag



Reverting to a state prior to an external snapshot risks
corrupting any other branches in the snapshot hierarchy that
were using the snapshot as a read-only backing file.  So
disk snapshot code will default to preventing reverting to
a snapshot that has any children, meaning that deleting just
the children of a snapshot becomes a useful operation in
preparing that snapshot for being a future reversion target.
The code for the new flag is simple - it's one less deletion,
plus a tweak to keep the current snapshot correct.

* include/libvirt/libvirt.h.in
(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY): New flag.
* src/libvirt.c (virDomainSnapshotDelete): Document it, and
enforce mutual exclusion.
* src/qemu/qemu_driver.c (qemuDomainSnapshotDelete): Implement
it.
---
 include/libvirt/libvirt.h.in |    1 +
 src/libvirt.c                |   32 +++++++++++++++++++++++---------
 src/qemu/qemu_driver.c       |   25 +++++++++++++++++++++----
 3 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 4a5dbff..64441d9 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2620,6 +2620,7 @@ int virDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
 typedef enum {
     VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN      = (1 << 0), /* Also delete children */
     VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY = (1 << 1), /* Delete just metadata */
+    VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY = (1 << 2), /* Delete just children */
 } virDomainSnapshotDeleteFlags;

 int virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
diff --git a/src/libvirt.c b/src/libvirt.c
index 3ab2ea5..9b3d2b6 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -16052,16 +16052,22 @@ error:
  *
  * Delete the snapshot.
  *
- * If @flags is 0, then just this snapshot is deleted, and changes from
- * this snapshot are automatically merged into children snapshots.  If
- * @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, then this snapshot
- * and any children snapshots are deleted.  If @flags includes
- * VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, then any snapshot metadata
- * tracked by libvirt is removed while keeping the snapshot contents
- * intact; if a hypervisor does not require any libvirt metadata to
- * track snapshots, then this flag is silently ignored.
+ * If @flags is 0, then just this snapshot is deleted, and changes
+ * from this snapshot are automatically merged into children
+ * snapshots.  If @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN,
+ * then this snapshot and any descendant snapshots are deleted.  If
+ * @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, then any
+ * descendant snapshots are deleted, but this snapshot remains.  These
+ * two flags are mutually exclusive.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, then
+ * any snapshot metadata tracked by libvirt is removed while keeping
+ * the snapshot contents intact; if a hypervisor does not require any
+ * libvirt metadata to track snapshots, then this flag is silently
+ * ignored.
  *
- * Returns 0 if the snapshot was successfully deleted, -1 on error.
+ * Returns 0 if the selected snapshot(s) were successfully deleted,
+ * -1 on error.
  */
 int
 virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
@@ -16086,6 +16092,14 @@ virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
         goto error;
     }

+    if ((flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) &&
+        (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
+        virLibDomainError(VIR_ERR_INVALID_ARG,
+                          _("children and children_only flags are "
+                            "mutually exclusive"));
+        goto error;
+    }
+
     if (conn->driver->domainSnapshotDelete) {
         int ret = conn->driver->domainSnapshotDelete(snapshot, flags);
         if (ret < 0)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index df51d83..3aefaef 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9463,7 +9463,8 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
     bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);

     virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
-                  VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, -1);
+                  VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY |
+                  VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);

     qemuDriverLock(driver);
     virUUIDFormat(snapshot->domain->uuid, uuidstr);
@@ -9485,7 +9486,8 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
     if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
         goto cleanup;

-    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) {
+    if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
+                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
         rem.driver = driver;
         rem.vm = vm;
         rem.metadata_only = metadata_only;
@@ -9497,8 +9499,20 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                                            &rem);
         if (rem.err < 0)
             goto endjob;
-        if (rem.current)
+        if (rem.current) {
+            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
+                snap->def->current = true;
+                if (qemuDomainSnapshotWriteMetadata(vm, snap,
+                                                    driver->snapshotDir) < 0) {
+                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                    _("failed to set snapshot '%s' as current"),
+                                    snap->def->name);
+                    snap->def->current = false;
+                    goto endjob;
+                }
+            }
             vm->current_snapshot = snap;
+        }
     } else {
         rep.driver = driver;
         rep.parent = snap->def->parent;
@@ -9511,7 +9525,10 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
             goto endjob;
     }

-    ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
+    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
+        ret = 0;
+    else
+        ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);

 endjob:
     if (qemuDomainObjEndJob(driver, vm) == 0)
-- 
1.7.4.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]