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.
* 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 | 11 ++++++++---
3 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 36f1b34..49fe6b3 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2607,6 +2607,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 fac2047..2c84e7e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -15857,16 +15857,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.
*
- * Returns 0 if the snapshot was successfully deleted, -1 on error.
+ * 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 selected snapshot(s) were successfully deleted,
+ * -1 on error.
*/
int
virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
@@ -15891,6 +15897,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 d46baba..a8cd9f8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9257,7 +9257,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);
@@ -9279,7 +9280,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;
@@ -9302,7 +9304,10 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
goto endjob;
}
- ret = qemuDomainSnapshotDiscard(driver, vm, snap, metadata_only);
+ if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
+ ret = 0;
+ else
+ ret = qemuDomainSnapshotDiscard(driver, vm, snap, metadata_only);
endjob:
if (qemuDomainObjEndJob(driver, vm) == 0)
--
1.7.4.4