Pull out the portion of virDomainSnapshotRefinePrep() that deals
with definition sanity into a separate helper routine that can
be reused with bulk redefine, leaving behind only the code
specific to loop checking and in-place updates that are only
needed in single-definition handling.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
src/conf/snapshot_conf.c | 186 ++++++++++++++++++++-------------------
1 file changed, 96 insertions(+), 90 deletions(-)
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index 386ec82d15..a5b05eadf4 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -426,6 +426,87 @@ virDomainSnapshotDefParseString(const char *xmlStr,
}
+/* Perform sanity checking on a redefined snapshot definition. If
+ * @other is non-NULL, this may include swapping def->dom from other
+ * into def. */
+static int
+virDomainSnapshotRedefineValidate(virDomainSnapshotDefPtr def,
+ const unsigned char *domain_uuid,
+ virDomainSnapshotObjPtr other,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags)
+{
+ int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
+ bool align_match = true;
+ bool external = def->state == VIR_SNAP_STATE_DISK_SNAPSHOT ||
+ virDomainSnapshotDefIsExternal(def);
+
+ if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) && !external) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("disk-only flag for snapshot %s requires "
+ "disk-snapshot state"),
+ def->name);
+ return -1;
+ }
+ if (def->dom && memcmp(def->dom->uuid, domain_uuid,
VIR_UUID_BUFLEN)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(domain_uuid, uuidstr);
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("definition for snapshot %s must use uuid %s"),
+ def->name, uuidstr);
+ return -1;
+ }
+
+ if (other) {
+ if ((other->def->state == VIR_SNAP_STATE_RUNNING ||
+ other->def->state == VIR_SNAP_STATE_PAUSED) !=
+ (def->state == VIR_SNAP_STATE_RUNNING ||
+ def->state == VIR_SNAP_STATE_PAUSED)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("cannot change between online and offline "
+ "snapshot state in snapshot %s"),
+ def->name);
+ return -1;
+ }
+
+ if ((other->def->state == VIR_SNAP_STATE_DISK_SNAPSHOT) !=
+ (def->state == VIR_SNAP_STATE_DISK_SNAPSHOT)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("cannot change between disk only and "
+ "full system in snapshot %s"),
+ def->name);
+ return -1;
+ }
+
+ if (other->def->dom) {
+ if (def->dom) {
+ if (!virDomainDefCheckABIStability(other->def->dom,
+ def->dom, xmlopt))
+ return -1;
+ } else {
+ /* Transfer the domain def */
+ def->dom = other->def->dom;
+ other->def->dom = NULL;
+ }
+ }
+ }
+
+ if (def->dom) {
+ if (external) {
+ align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
+ align_match = false;
+ }
+ if (virDomainSnapshotAlignDisks(def, align_location,
+ align_match) < 0)
+ return -1;
+ }
+
+
+ return 0;
+}
+
+
/**
* virDomainSnapshotDefAssignExternalNames:
* @def: snapshot def object
@@ -1325,12 +1406,8 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
unsigned int flags)
{
virDomainSnapshotDefPtr def = *defptr;
- int ret = -1;
- int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
- bool align_match = true;
virDomainSnapshotObjPtr other;
- bool external = def->state == VIR_SNAP_STATE_DISK_SNAPSHOT ||
- virDomainSnapshotDefIsExternal(def);
+ bool check_stolen;
/* Prevent circular chains */
if (def->parent) {
@@ -1338,21 +1415,21 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
virReportError(VIR_ERR_INVALID_ARG,
_("cannot set snapshot %s as its own parent"),
def->name);
- goto cleanup;
+ return -1;
}
other = virDomainSnapshotFindByName(vm->snapshots, def->parent);
if (!other) {
virReportError(VIR_ERR_INVALID_ARG,
_("parent %s for snapshot %s not found"),
def->parent, def->name);
- goto cleanup;
+ return -1;
}
while (other->def->parent) {
if (STREQ(other->def->parent, def->name)) {
virReportError(VIR_ERR_INVALID_ARG,
_("parent %s would create cycle to %s"),
other->def->name, def->name);
- goto cleanup;
+ return -1;
}
other = virDomainSnapshotFindByName(vm->snapshots,
other->def->parent);
@@ -1364,77 +1441,18 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
}
}
- /* Check that any replacement is compatible */
- if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) && !external) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("disk-only flag for snapshot %s requires "
- "disk-snapshot state"),
- def->name);
- goto cleanup;
- }
-
- if (def->dom &&
- memcmp(def->dom->uuid, domain->uuid, VIR_UUID_BUFLEN)) {
- char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(domain->uuid, uuidstr);
- virReportError(VIR_ERR_INVALID_ARG,
- _("definition for snapshot %s must use uuid %s"),
- def->name, uuidstr);
- goto cleanup;
- }
-
other = virDomainSnapshotFindByName(vm->snapshots, def->name);
+ check_stolen = other && other->def->dom;
+ if (virDomainSnapshotRedefineValidate(def, domain->uuid, other, xmlopt,
+ flags) < 0) {
+ /* revert stealing of the snapshot domain definition */
+ if (check_stolen && def->dom && !other->def->dom) {
+ other->def->dom = def->dom;
+ def->dom = NULL;
+ }
+ return -1;
+ }
if (other) {
- if ((other->def->state == VIR_SNAP_STATE_RUNNING ||
- other->def->state == VIR_SNAP_STATE_PAUSED) !=
- (def->state == VIR_SNAP_STATE_RUNNING ||
- def->state == VIR_SNAP_STATE_PAUSED)) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("cannot change between online and offline "
- "snapshot state in snapshot %s"),
- def->name);
- goto cleanup;
- }
-
- if ((other->def->state == VIR_SNAP_STATE_DISK_SNAPSHOT) !=
- (def->state == VIR_SNAP_STATE_DISK_SNAPSHOT)) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("cannot change between disk only and "
- "full system in snapshot %s"),
- def->name);
- goto cleanup;
- }
-
- if (other->def->dom) {
- if (def->dom) {
- if (!virDomainDefCheckABIStability(other->def->dom,
- def->dom, xmlopt))
- goto cleanup;
- } else {
- /* Transfer the domain def */
- def->dom = other->def->dom;
- other->def->dom = NULL;
- }
- }
-
- if (def->dom) {
- if (external) {
- align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
- align_match = false;
- }
-
- if (virDomainSnapshotAlignDisks(def, align_location,
- align_match) < 0) {
- /* revert stealing of the snapshot domain definition */
- if (def->dom && !other->def->dom) {
- other->def->dom = def->dom;
- def->dom = NULL;
- }
- goto cleanup;
- }
- }
-
if (other == vm->current_snapshot) {
*update_current = true;
vm->current_snapshot = NULL;
@@ -1447,19 +1465,7 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
other->def = def;
*defptr = NULL;
*snap = other;
- } else {
- if (def->dom) {
- if (external) {
- align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
- align_match = false;
- }
- if (virDomainSnapshotAlignDisks(def, align_location,
- align_match) < 0)
- goto cleanup;
- }
}
- ret = 0;
- cleanup:
- return ret;
+ return 0;
}
--
2.20.1