virDomainSnapshotRedefinePrep: Don't do partial redefine

'virDomainSnapshotRedefinePrep' does everything needed for a redefine
when the snapshot exists but not when we are defining metadata for a new
snapshot. This gives us weird semantics.

Extract the code for replacing the definition of an existing snapshot
into a new helper 'virDomainSnapshotReplaceDef' and refactor all
callers.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2022-01-12 17:00:22 +01:00
parent d281c1323f
commit 717f1cc4d1
7 changed files with 36 additions and 24 deletions

View File

@ -957,12 +957,11 @@ virDomainSnapshotIsExternal(virDomainMomentObj *snap)
int int
virDomainSnapshotRedefinePrep(virDomainObj *vm, virDomainSnapshotRedefinePrep(virDomainObj *vm,
virDomainSnapshotDef **defptr, virDomainSnapshotDef *snapdef,
virDomainMomentObj **snap, virDomainMomentObj **snap,
virDomainXMLOption *xmlopt, virDomainXMLOption *xmlopt,
unsigned int flags) unsigned int flags)
{ {
virDomainSnapshotDef *snapdef = *defptr;
virDomainMomentObj *other; virDomainMomentObj *other;
virDomainSnapshotDef *otherSnapDef = NULL; virDomainSnapshotDef *otherSnapDef = NULL;
virDomainDef *otherDomDef = NULL; virDomainDef *otherDomDef = NULL;
@ -976,6 +975,8 @@ virDomainSnapshotRedefinePrep(virDomainObj *vm,
otherDomDef = otherSnapDef->parent.dom; otherDomDef = otherSnapDef->parent.dom;
} }
*snap = other;
if (virDomainSnapshotRedefineValidate(snapdef, vm->def->uuid, other, xmlopt, flags) < 0) if (virDomainSnapshotRedefineValidate(snapdef, vm->def->uuid, other, xmlopt, flags) < 0)
return -1; return -1;
@ -986,20 +987,5 @@ virDomainSnapshotRedefinePrep(virDomainObj *vm,
if (virDomainSnapshotAlignDisks(snapdef, otherDomDef, align_location, true) < 0) if (virDomainSnapshotAlignDisks(snapdef, otherDomDef, align_location, true) < 0)
return -1; return -1;
if (other) {
/* steal the domain definition if redefining an existing snapshot which
* with a snapshot definition lacking the domain definition */
if (!snapdef->parent.dom)
snapdef->parent.dom = g_steal_pointer(&otherSnapDef->parent.dom);
/* Drop and rebuild the parent relationship, but keep all
* child relations by reusing snap. */
virDomainMomentDropParent(other);
virObjectUnref(otherSnapDef);
other->def = &(*defptr)->parent;
*defptr = NULL;
*snap = other;
}
return 0; return 0;
} }

View File

@ -134,7 +134,7 @@ bool virDomainSnapshotDefIsExternal(virDomainSnapshotDef *def);
bool virDomainSnapshotIsExternal(virDomainMomentObj *snap); bool virDomainSnapshotIsExternal(virDomainMomentObj *snap);
int virDomainSnapshotRedefinePrep(virDomainObj *vm, int virDomainSnapshotRedefinePrep(virDomainObj *vm,
virDomainSnapshotDef **def, virDomainSnapshotDef *snapdef,
virDomainMomentObj **snap, virDomainMomentObj **snap,
virDomainXMLOption *xmlopt, virDomainXMLOption *xmlopt,
unsigned int flags); unsigned int flags);

View File

@ -54,6 +54,25 @@ virDomainSnapshotAssignDef(virDomainSnapshotObjList *snapshots,
} }
void
virDomainSnapshotReplaceDef(virDomainMomentObj *snap,
virDomainSnapshotDef **snapdefptr)
{
virDomainSnapshotDef *snapdef = *snapdefptr;
g_autoptr(virDomainSnapshotDef) origsnapdef = virDomainSnapshotObjGetDef(snap);
/* steal the domain definition if redefining an existing snapshot which
* with a snapshot definition lacking the domain definition */
if (!snapdef->parent.dom)
snapdef->parent.dom = g_steal_pointer(&origsnapdef->parent.dom);
/* Drop and rebuild the parent relationship, but keep all child relations by reusing snap. */
virDomainMomentDropParent(snap);
snap->def = &snapdef->parent;
*snapdefptr = NULL;
}
static bool static bool
virDomainSnapshotFilter(virDomainMomentObj *obj, virDomainSnapshotFilter(virDomainMomentObj *obj,
unsigned int flags) unsigned int flags)

View File

@ -32,6 +32,9 @@ void virDomainSnapshotObjListFree(virDomainSnapshotObjList *snapshots);
virDomainMomentObj *virDomainSnapshotAssignDef(virDomainSnapshotObjList *snapshots, virDomainMomentObj *virDomainSnapshotAssignDef(virDomainSnapshotObjList *snapshots,
virDomainSnapshotDef **snapdefptr); virDomainSnapshotDef **snapdefptr);
void virDomainSnapshotReplaceDef(virDomainMomentObj *snap,
virDomainSnapshotDef **snapdefptr);
int virDomainSnapshotObjListGetNames(virDomainSnapshotObjList *snapshots, int virDomainSnapshotObjListGetNames(virDomainSnapshotObjList *snapshots,
virDomainMomentObj *from, virDomainMomentObj *from,
char **const names, int maxnames, char **const names, int maxnames,

View File

@ -1212,6 +1212,7 @@ virDomainSnapshotObjListNew;
virDomainSnapshotObjListNum; virDomainSnapshotObjListNum;
virDomainSnapshotObjListRemove; virDomainSnapshotObjListRemove;
virDomainSnapshotObjListRemoveAll; virDomainSnapshotObjListRemoveAll;
virDomainSnapshotReplaceDef;
virDomainSnapshotSetCurrent; virDomainSnapshotSetCurrent;
virDomainSnapshotUpdateRelations; virDomainSnapshotUpdateRelations;

View File

@ -1715,15 +1715,16 @@ qemuSnapshotRedefine(virDomainObj *vm,
virDomainSnapshotPtr ret = NULL; virDomainSnapshotPtr ret = NULL;
g_autoptr(virDomainSnapshotDef) snapdef = virObjectRef(snapdeftmp); g_autoptr(virDomainSnapshotDef) snapdef = virObjectRef(snapdeftmp);
if (virDomainSnapshotRedefinePrep(vm, &snapdef, &snap, if (virDomainSnapshotRedefinePrep(vm, snapdef, &snap, driver->xmlopt, flags) < 0)
driver->xmlopt,
flags) < 0)
return NULL; return NULL;
if (!snap) { if (snap) {
virDomainSnapshotReplaceDef(snap, &snapdef);
} else {
if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, &snapdef))) if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, &snapdef)))
return NULL; return NULL;
} }
/* XXX Should we validate that the redefined snapshot even /* XXX Should we validate that the redefined snapshot even
* makes sense, such as checking that qemu-img recognizes the * makes sense, such as checking that qemu-img recognizes the
* snapshot name in at least one of the domain's disks? */ * snapshot name in at least one of the domain's disks? */

View File

@ -8749,10 +8749,12 @@ testDomainSnapshotRedefine(virDomainObj *vm,
virDomainMomentObj *snap = NULL; virDomainMomentObj *snap = NULL;
g_autoptr(virDomainSnapshotDef) snapdef = virObjectRef(snapdeftmp); g_autoptr(virDomainSnapshotDef) snapdef = virObjectRef(snapdeftmp);
if (virDomainSnapshotRedefinePrep(vm, &snapdef, &snap, xmlopt, flags) < 0) if (virDomainSnapshotRedefinePrep(vm, snapdef, &snap, xmlopt, flags) < 0)
return NULL; return NULL;
if (!snap) { if (snap) {
virDomainSnapshotReplaceDef(snap, &snapdef);
} else {
if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, &snapdef))) if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, &snapdef)))
return NULL; return NULL;
} }