qemu_snapshot: refactor validation of snapshot delete

Prepare the validation function for external snapshot delete support.

There is one exception when deleting `children-only` snapshots. If the
snapshot tree is like this example:

    snap1 (external)
     |
     +- snap2 (internal)
         |
         +- snap3 (internal)
             |
             +- snap4 (internal)

and user calls `snapshot-delete snap1 --children-only` the current
snapshot is external but all the children snapshots are internal only
and we are able to delete it.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Pavel Hrdina 2022-08-23 13:18:35 +02:00
parent 86883588c7
commit 4475c69787

View File

@ -100,21 +100,6 @@ qemuSnapObjFromSnapshot(virDomainObj *vm,
} }
/* Count how many snapshots in a set are external snapshots. */
static int
qemuSnapshotCountExternal(void *payload,
const char *name G_GNUC_UNUSED,
void *data)
{
virDomainMomentObj *snap = payload;
int *count = data;
if (virDomainSnapshotIsExternal(snap))
(*count)++;
return 0;
}
int int
qemuSnapshotFSFreeze(virDomainObj *vm, qemuSnapshotFSFreeze(virDomainObj *vm,
const char **mountpoints, const char **mountpoints,
@ -2482,26 +2467,60 @@ qemuSnapshotDeleteChildren(virDomainObj *vm,
} }
typedef struct {
int external;
int internal;
} qemuSnapshotCount;
static int
qemuSnapshotCountExternalInternal(void *payload,
const char *name G_GNUC_UNUSED,
void *data)
{
virDomainMomentObj *snap = payload;
qemuSnapshotCount *count = data;
if (virDomainSnapshotIsExternal(snap)) {
count->external++;
} else {
count->internal++;
}
return 0;
}
static int static int
qemuSnapshotDeleteValidate(virDomainMomentObj *snap, qemuSnapshotDeleteValidate(virDomainMomentObj *snap,
unsigned int flags) unsigned int flags)
{ {
int external = 0;
if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
virDomainSnapshotIsExternal(snap))
external++;
if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
virDomainMomentForEachDescendant(snap, qemuSnapshotCount count = { 0 };
qemuSnapshotCountExternal,
&external);
if (external) { virDomainMomentForEachDescendant(snap,
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, qemuSnapshotCountExternalInternal,
_("deletion of %d external disk snapshots not " &count);
"supported yet"), external);
if (count.external > 0 && count.internal > 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("deletion of external and internal children disk snapshots not supported"));
return -1;
}
if (count.external > 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("deletion of external children disk snapshots not supported"));
return -1;
}
}
if (virDomainSnapshotIsExternal(snap) &&
!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("deletion of external disk snapshots not supported"));
return -1; return -1;
} }