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 {
|
typedef enum {
|
||||||
VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN = (1 << 0), /* Also delete children */
|
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_METADATA_ONLY = (1 << 1), /* Delete just metadata */
|
||||||
|
VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY = (1 << 2), /* Delete just children */
|
||||||
} virDomainSnapshotDeleteFlags;
|
} virDomainSnapshotDeleteFlags;
|
||||||
|
|
||||||
int virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
int virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
||||||
|
@ -16057,16 +16057,22 @@ error:
|
|||||||
*
|
*
|
||||||
* Delete the snapshot.
|
* Delete the snapshot.
|
||||||
*
|
*
|
||||||
* If @flags is 0, then just this snapshot is deleted, and changes from
|
* If @flags is 0, then just this snapshot is deleted, and changes
|
||||||
* this snapshot are automatically merged into children snapshots. If
|
* from this snapshot are automatically merged into children
|
||||||
* @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, then this snapshot
|
* snapshots. If @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN,
|
||||||
* and any children snapshots are deleted. If @flags includes
|
* then this snapshot and any descendant snapshots are deleted. If
|
||||||
* VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, then any snapshot metadata
|
* @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, then any
|
||||||
* tracked by libvirt is removed while keeping the snapshot contents
|
* descendant snapshots are deleted, but this snapshot remains. These
|
||||||
* intact; if a hypervisor does not require any libvirt metadata to
|
* two flags are mutually exclusive.
|
||||||
* track snapshots, then this flag is silently ignored.
|
|
||||||
*
|
*
|
||||||
* 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
|
int
|
||||||
virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
||||||
@ -16091,6 +16097,14 @@ virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
|||||||
goto error;
|
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) {
|
if (conn->driver->domainSnapshotDelete) {
|
||||||
int ret = conn->driver->domainSnapshotDelete(snapshot, flags);
|
int ret = conn->driver->domainSnapshotDelete(snapshot, flags);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -9512,7 +9512,8 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
|||||||
bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);
|
bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);
|
||||||
|
|
||||||
virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
|
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);
|
qemuDriverLock(driver);
|
||||||
virUUIDFormat(snapshot->domain->uuid, uuidstr);
|
virUUIDFormat(snapshot->domain->uuid, uuidstr);
|
||||||
@ -9534,7 +9535,8 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
|||||||
if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
|
if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
|
||||||
goto cleanup;
|
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.driver = driver;
|
||||||
rem.vm = vm;
|
rem.vm = vm;
|
||||||
rem.metadata_only = metadata_only;
|
rem.metadata_only = metadata_only;
|
||||||
@ -9546,8 +9548,20 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
|||||||
&rem);
|
&rem);
|
||||||
if (rem.err < 0)
|
if (rem.err < 0)
|
||||||
goto endjob;
|
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;
|
vm->current_snapshot = snap;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rep.driver = driver;
|
rep.driver = driver;
|
||||||
rep.parent = snap->def->parent;
|
rep.parent = snap->def->parent;
|
||||||
@ -9560,6 +9574,9 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)
|
||||||
|
ret = 0;
|
||||||
|
else
|
||||||
ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
|
ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
|
||||||
|
|
||||||
endjob:
|
endjob:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user