mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
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:
parent
e91d27ee45
commit
3d77d0a644
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user