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.
This commit is contained in:
Eric Blake 2011-08-16 16:23:45 -06:00
parent e91d27ee45
commit 3d77d0a644
3 changed files with 45 additions and 13 deletions

View File

@ -2622,6 +2622,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,

View File

@ -16057,16 +16057,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,
@ -16091,6 +16097,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)

View File

@ -9512,7 +9512,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);
@ -9534,7 +9535,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;
@ -9546,8 +9548,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;
@ -9560,7 +9574,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)