[libvirt] [PATCH 39/26] snapshot: reject unimplemented disk snapshot features

Eric Blake eblake at redhat.com
Mon Aug 22 22:55:53 UTC 2011


On 08/22/2011 02:41 PM, Eric Blake wrote:
> My RFC for snapshot support [1] proposes several rules for when it is
> safe to delete or revert to an external snapshot, predicated on
> the existence of new API flags.  These will be incrementally added
> in future patches, but until then, blindly mishandling a disk
> snapshot risks corrupting internal state, so it is better to
> outright reject the attempts until the other pieces are in place,
> thus incrementally relaxing the restrictions added in this patch.
>
> [1] https://www.redhat.com/archives/libvir-list/2011-August/msg00361.html
>
> * src/qemu/qemu_driver.c (qemuDomainSnapshotCountExternal): New
> function.
> (qemuDomainSnapshotDelete): Use it to add safety valve.
> (qemuDomainRevertToSnapshot): Add safety valve.

> @@ -9293,6 +9314,16 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
>           goto cleanup;
>       }
>
> +    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
> +        (virDomainSnapshotForEachDescendant(&vm->snapshots, snap,
> +                                            qemuDomainSnapshotCountExternal,
> +&external)&&  external)) {
> +        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                        _("deletion of external disk snapshots not supported "
> +                          "yet"));
> +        goto cleanup;
> +    }

This was a little too strict - I couldn't even get rid of my metadata, 
which should always be a safe operation.  Conversely, undefine and 
destroy with the options to delete *_SNAPSHOT_FULL should also be 
complaining.  Squash this in:

diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c
index bf3c137..9f3102b 100644
--- i/src/qemu/qemu_driver.c
+++ w/src/qemu/qemu_driver.c
@@ -1777,6 +1777,19 @@ qemuDomainSnapshotDiscardAll(void *payload,
          curr->err = err;
  }

+/* Count how many snapshots in a set have external disk snapshots.  */
+static void
+qemuDomainSnapshotCountExternal(void *payload,
+                                const void *name ATTRIBUTE_UNUSED,
+                                void *data)
+{
+    virDomainSnapshotObjPtr snap = payload;
+    int *count = data;
+
+    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT)
+        (*count)++;
+}
+
  static int
  qemuDomainDestroyFlags(virDomainPtr dom,
                         unsigned int flags)
@@ -1787,6 +1800,7 @@ qemuDomainDestroyFlags(virDomainPtr dom,
      virDomainEventPtr event = NULL;
      qemuDomainObjPrivatePtr priv;
      int nsnapshots;
+    int external = 0;

      virCheckFlags(VIR_DOMAIN_DESTROY_SNAPSHOTS_METADATA |
                    VIR_DOMAIN_DESTROY_SNAPSHOTS_FULL, -1);
@@ -1814,6 +1828,16 @@ qemuDomainDestroyFlags(virDomainPtr dom,
              goto cleanup;
          }

+        if ((flags & VIR_DOMAIN_DESTROY_SNAPSHOTS_FULL) &&
+            virHashForEach(vm->snapshots.objs, 
qemuDomainSnapshotCountExternal,
+                           &external) &&
+            external) {
+            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                            _("deletion of %d external disk snapshots not "
+                              "supported yet"), external);
+            goto cleanup;
+        }
+
          rem.driver = driver;
          rem.vm = vm;
          rem.metadata_only = !(flags & VIR_DOMAIN_DESTROY_SNAPSHOTS_FULL);
@@ -4943,6 +4967,7 @@ qemuDomainUndefineFlags(virDomainPtr dom,
      char *name = NULL;
      int ret = -1;
      int nsnapshots;
+    int external = 0;

      virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                    VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
@@ -4972,6 +4997,16 @@ qemuDomainUndefineFlags(virDomainPtr dom,
              goto cleanup;
          }

+        if ((flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_FULL) &&
+            virHashForEach(vm->snapshots.objs, 
qemuDomainSnapshotCountExternal,
+                           &external) &&
+            external) {
+            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                            _("deletion of %d external disk snapshots not "
+                              "supported yet"), external);
+            goto cleanup;
+        }
+
          rem.driver = driver;
          rem.vm = vm;
          rem.metadata_only = !(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_FULL);
@@ -9502,19 +9537,6 @@ qemuDomainSnapshotReparentChildren(void *payload,
                                                 rep->driver->snapshotDir);
  }

-/* Count how many snapshots in a set have external disk snapshots.  */
-static void
-qemuDomainSnapshotCountExternal(void *payload,
-                                const void *name ATTRIBUTE_UNUSED,
-                                void *data)
-{
-    virDomainSnapshotObjPtr snap = payload;
-    int *count = data;
-
-    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT)
-        (*count)++;
-}
-
  static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                                      unsigned int flags)
  {
@@ -9549,10 +9571,11 @@ static int 
qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
          goto cleanup;
      }

-    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
-        (virDomainSnapshotForEachDescendant(&vm->snapshots, snap,
- 
qemuDomainSnapshotCountExternal,
-                                            &external) && external)) {
+    if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) &&
+        (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
+         (virDomainSnapshotForEachDescendant(&vm->snapshots, snap,
+ 
qemuDomainSnapshotCountExternal,
+                                             &external) && external))) {
          qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                          _("deletion of external disk snapshots not 
supported "
                            "yet"));


-- 
Eric Blake   eblake at redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org




More information about the libvir-list mailing list