The only use for the 'current' member of virDomainSnapshotDef was with the PARSE/FORMAT_INTERNAL flag for controlling an internal-use <active> element marking whether a particular snapshot definition was current, and even then, only by the qemu driver on output, and by qemu and test driver on input. But this duplicates vm->snapshot_current, and gets in the way of potential simplifications to have qemu store a single file for all snapshots rather than one file per snapshot. Get rid of the member by adding a bool* parameter during parse (ignored if the PARSE_INTERNAL flag is not set), and by adding a new flag during format (if FORMAT_INTERNAL is set, the value printed in <active> depends on the new FORMAT_CURRENT). Then update the qemu driver accordingly. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/conf/snapshot_conf.h | 6 ++-- src/conf/snapshot_conf.c | 18 ++++++---- src/conf/virdomainsnapshotobjlist.c | 4 +-- src/esx/esx_driver.c | 2 +- src/qemu/qemu_domain.c | 18 +++++----- src/qemu/qemu_driver.c | 51 +++++++++++++++-------------- src/test/test_driver.c | 5 ++- src/vbox/vbox_common.c | 4 +-- src/vz/vz_driver.c | 3 +- tests/domainsnapshotxml2xmltest.c | 5 ++- 10 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h index 7230b9950f..b13a500af4 100644 --- a/src/conf/snapshot_conf.h +++ b/src/conf/snapshot_conf.h @@ -88,9 +88,6 @@ struct _virDomainSnapshotDef { virDomainDefPtr dom; virObjectPtr cookie; - - /* Internal use. */ - bool current; /* At most one snapshot in the list should have this set */ }; typedef enum { @@ -103,6 +100,7 @@ typedef enum { typedef enum { VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE = 1 << 0, VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL = 1 << 1, + VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT = 1 << 2, } virDomainSnapshotFormatFlags; unsigned int virDomainSnapshotFormatConvertXMLFlags(unsigned int flags); @@ -110,11 +108,13 @@ unsigned int virDomainSnapshotFormatConvertXMLFlags(unsigned int flags); virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, virCapsPtr caps, virDomainXMLOptionPtr xmlopt, + bool *current, unsigned int flags); virDomainSnapshotDefPtr virDomainSnapshotDefParseNode(xmlDocPtr xml, xmlNodePtr root, virCapsPtr caps, virDomainXMLOptionPtr xmlopt, + bool *current, unsigned int flags); void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def); char *virDomainSnapshotDefFormat(const char *uuidstr, diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index ffb1313c89..bf5fdc0647 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -184,12 +184,14 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node, /* flags is bitwise-or of virDomainSnapshotParseFlags. * If flags does not include VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE, then - * caps are ignored. + * caps are ignored. If flags does not include + * VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL, then current is ignored. */ static virDomainSnapshotDefPtr virDomainSnapshotDefParse(xmlXPathContextPtr ctxt, virCapsPtr caps, virDomainXMLOptionPtr xmlopt, + bool *current, unsigned int flags) { virDomainSnapshotDefPtr def = NULL; @@ -350,7 +352,7 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt, _("Could not find 'active' element")); goto cleanup; } - def->current = active != 0; + *current = active != 0; } if (!offline && virSaveCookieParse(ctxt, &def->cookie, saveCookie) < 0) @@ -374,6 +376,7 @@ virDomainSnapshotDefParseNode(xmlDocPtr xml, xmlNodePtr root, virCapsPtr caps, virDomainXMLOptionPtr xmlopt, + bool *current, unsigned int flags) { xmlXPathContextPtr ctxt = NULL; @@ -391,7 +394,7 @@ virDomainSnapshotDefParseNode(xmlDocPtr xml, } ctxt->node = root; - def = virDomainSnapshotDefParse(ctxt, caps, xmlopt, flags); + def = virDomainSnapshotDefParse(ctxt, caps, xmlopt, current, flags); cleanup: xmlXPathFreeContext(ctxt); return def; @@ -401,6 +404,7 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, virCapsPtr caps, virDomainXMLOptionPtr xmlopt, + bool *current, unsigned int flags) { virDomainSnapshotDefPtr ret = NULL; @@ -410,7 +414,7 @@ virDomainSnapshotDefParseString(const char *xmlStr, if ((xml = virXMLParse(NULL, xmlStr, _("(domain_snapshot)")))) { xmlKeepBlanksDefault(keepBlanksDefault); ret = virDomainSnapshotDefParseNode(xml, xmlDocGetRootElement(xml), - caps, xmlopt, flags); + caps, xmlopt, current, flags); xmlFreeDoc(xml); } xmlKeepBlanksDefault(keepBlanksDefault); @@ -849,7 +853,8 @@ virDomainSnapshotDefFormatInternal(virBufferPtr buf, goto error; if (flags & VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL) - virBufferAsprintf(buf, "<active>%d</active>\n", def->current); + virBufferAsprintf(buf, "<active>%d</active>\n", + !!(flags & VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT)); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</domainsnapshot>\n"); @@ -875,7 +880,8 @@ virDomainSnapshotDefFormat(const char *uuidstr, virBuffer buf = VIR_BUFFER_INITIALIZER; virCheckFlags(VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE | - VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL, NULL); + VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL | + VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT, NULL); if (virDomainSnapshotDefFormatInternal(&buf, uuidstr, def, caps, xmlopt, flags) < 0) return NULL; diff --git a/src/conf/virdomainsnapshotobjlist.c b/src/conf/virdomainsnapshotobjlist.c index e2f2110108..be44bdde71 100644 --- a/src/conf/virdomainsnapshotobjlist.c +++ b/src/conf/virdomainsnapshotobjlist.c @@ -108,7 +108,8 @@ virDomainSnapshotObjListParse(const char *xmlStr, virDomainSnapshotDefPtr def; virDomainSnapshotObjPtr snap; - def = virDomainSnapshotDefParseNode(xml, nodes[i], caps, xmlopt, flags); + def = virDomainSnapshotDefParseNode(xml, nodes[i], caps, xmlopt, NULL, + flags); if (!def) goto cleanup; if (!(snap = virDomainSnapshotAssignDef(snapshots, def))) { @@ -134,7 +135,6 @@ virDomainSnapshotObjListParse(const char *xmlStr, _("no snapshot matching current='%s'"), current); goto cleanup; } - (*current_snap)->def->current = true; } ret = 0; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index c016f8051f..1c6a2dcb71 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4102,7 +4102,7 @@ esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, return NULL; def = virDomainSnapshotDefParseString(xmlDesc, priv->caps, - priv->xmlopt, 0); + priv->xmlopt, NULL, 0); if (!def) return NULL; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 86e80391e1..f8387339f0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8458,11 +8458,14 @@ qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm, char *snapDir = NULL; char *snapFile = NULL; char uuidstr[VIR_UUID_STRING_BUFLEN]; + unsigned int flags = VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE | + VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL; + if (vm->current_snapshot == snapshot) + flags |= VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT; virUUIDFormat(vm->def->uuid, uuidstr); - newxml = virDomainSnapshotDefFormat( - uuidstr, snapshot->def, caps, xmlopt, - VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE | VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL); + newxml = virDomainSnapshotDefFormat(uuidstr, snapshot->def, caps, xmlopt, + flags); if (newxml == NULL) return -1; @@ -8612,6 +8615,7 @@ qemuDomainSnapshotDiscard(virQEMUDriverPtr driver, goto cleanup; if (snap == vm->current_snapshot) { + vm->current_snapshot = NULL; if (update_parent && snap->def->parent) { parentsnap = virDomainSnapshotFindByName(vm->snapshots, snap->def->parent); @@ -8619,18 +8623,16 @@ qemuDomainSnapshotDiscard(virQEMUDriverPtr driver, VIR_WARN("missing parent snapshot matching name '%s'", snap->def->parent); } else { - parentsnap->def->current = true; + vm->current_snapshot = parentsnap; if (qemuDomainSnapshotWriteMetadata(vm, parentsnap, driver->caps, driver->xmlopt, cfg->snapshotDir) < 0) { VIR_WARN("failed to set parent snapshot '%s' as current", snap->def->parent); - parentsnap->def->current = false; - parentsnap = NULL; + vm->current_snapshot = NULL; } } } - vm->current_snapshot = parentsnap; } if (unlink(snapFile) < 0) @@ -8656,7 +8658,7 @@ int qemuDomainSnapshotDiscardAll(void *payload, virQEMUSnapRemovePtr curr = data; int err; - if (snap->def->current) + if (curr->vm->current_snapshot == snap) curr->current = true; err = qemuDomainSnapshotDiscard(curr->driver, curr->vm, snap, false, curr->metadata_only); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6e504dd17c..7e0e76a31a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -419,6 +419,7 @@ qemuDomainSnapshotLoad(virDomainObjPtr vm, virDomainSnapshotDefPtr def = NULL; virDomainSnapshotObjPtr snap = NULL; virDomainSnapshotObjPtr current = NULL; + bool cur; unsigned int flags = (VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE | VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL); @@ -465,7 +466,7 @@ qemuDomainSnapshotLoad(virDomainObjPtr vm, } def = virDomainSnapshotDefParseString(xmlStr, caps, - qemu_driver->xmlopt, + qemu_driver->xmlopt, &cur, flags); if (def == NULL) { /* Nothing we can do here, skip this one */ @@ -480,7 +481,7 @@ qemuDomainSnapshotLoad(virDomainObjPtr vm, snap = virDomainSnapshotAssignDef(vm->snapshots, def); if (snap == NULL) { virDomainSnapshotDefFree(def); - } else if (snap->def->current) { + } else if (cur) { current = snap; if (!vm->current_snapshot) vm->current_snapshot = snap; @@ -15661,6 +15662,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, virDomainSnapshotObjPtr snap = NULL; virDomainSnapshotPtr snapshot = NULL; virDomainSnapshotDefPtr def = NULL; + virDomainSnapshotObjPtr current = NULL; bool update_current = true; bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE; unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS; @@ -15722,7 +15724,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE; if (!(def = virDomainSnapshotDefParseString(xmlDesc, caps, driver->xmlopt, - parse_flags))) + NULL, parse_flags))) goto cleanup; /* reject snapshot names containing slashes or starting with dot as @@ -15856,19 +15858,17 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, def = NULL; } - if (update_current) - snap->def->current = true; - if (vm->current_snapshot) { + current = vm->current_snapshot; + if (current) { if (!redefine && - VIR_STRDUP(snap->def->parent, vm->current_snapshot->def->name) < 0) + VIR_STRDUP(snap->def->parent, current->def->name) < 0) goto endjob; if (update_current) { - vm->current_snapshot->def->current = false; - if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot, + vm->current_snapshot = NULL; + if (qemuDomainSnapshotWriteMetadata(vm, current, driver->caps, driver->xmlopt, cfg->snapshotDir) < 0) goto endjob; - vm->current_snapshot = NULL; } } @@ -15914,6 +15914,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, endjob: if (snapshot && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) { + if (update_current) + vm->current_snapshot = snap; if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps, driver->xmlopt, cfg->snapshotDir) < 0) { @@ -15925,9 +15927,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, _("unable to save metadata for snapshot %s"), snap->def->name); virDomainSnapshotObjListRemove(vm->snapshots, snap); + vm->current_snapshot = NULL; } else { - if (update_current) - vm->current_snapshot = snap; other = virDomainSnapshotFindByName(vm->snapshots, snap->def->parent); snap->parent = other; @@ -16347,6 +16348,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, virDomainObjPtr vm = NULL; int ret = -1; virDomainSnapshotObjPtr snap = NULL; + virDomainSnapshotObjPtr current = NULL; virObjectEventPtr event = NULL; virObjectEventPtr event2 = NULL; int detail; @@ -16441,14 +16443,13 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, } } - - if (vm->current_snapshot) { - vm->current_snapshot->def->current = false; - if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot, + current = vm->current_snapshot; + if (current) { + vm->current_snapshot = NULL; + if (qemuDomainSnapshotWriteMetadata(vm, current, driver->caps, driver->xmlopt, cfg->snapshotDir) < 0) goto endjob; - vm->current_snapshot = NULL; /* XXX Should we restore vm->current_snapshot after this point * in the failure cases where we know there was no change? */ } @@ -16458,7 +16459,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, * * XXX Should domain snapshots track live xml rather * than inactive xml? */ - snap->def->current = true; + vm->current_snapshot = snap; if (snap->def->dom) { config = virDomainDefCopy(snap->def->dom, caps, driver->xmlopt, NULL, true); @@ -16729,14 +16730,15 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, cleanup: if (ret == 0) { + vm->current_snapshot = snap; if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps, driver->xmlopt, - cfg->snapshotDir) < 0) + cfg->snapshotDir) < 0) { + vm->current_snapshot = NULL; ret = -1; - else - vm->current_snapshot = snap; + } } else if (snap) { - snap->def->current = false; + vm->current_snapshot = NULL; } if (ret == 0 && config && vm->persistent && !(ret = virDomainSaveConfig(cfg->configDir, driver->caps, @@ -16864,19 +16866,18 @@ qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, if (rem.err < 0) goto endjob; if (rem.current) { + vm->current_snapshot = snap; if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) { - snap->def->current = true; if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps, driver->xmlopt, cfg->snapshotDir) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set snapshot '%s' as current"), snap->def->name); - snap->def->current = false; + vm->current_snapshot = NULL; goto endjob; } } - vm->current_snapshot = snap; } } else if (snap->nchildren) { rep.cfg = cfg; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index e1ad9382e0..ca480c1b21 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -819,6 +819,7 @@ testParseDomainSnapshots(testDriverPtr privconn, int ret = -1; testDomainNamespaceDefPtr nsdata = domobj->def->namespaceData; xmlNodePtr *nodes = nsdata->snap_nodes; + bool cur; for (i = 0; i < nsdata->num_snap_nodes; i++) { virDomainSnapshotObjPtr snap; @@ -831,6 +832,7 @@ testParseDomainSnapshots(testDriverPtr privconn, def = virDomainSnapshotDefParseNode(ctxt->doc, node, privconn->caps, privconn->xmlopt, + &cur, VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL | VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); @@ -842,7 +844,7 @@ testParseDomainSnapshots(testDriverPtr privconn, goto error; } - if (def->current) { + if (cur) { if (domobj->current_snapshot) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("more than one snapshot claims to be active")); @@ -6363,6 +6365,7 @@ testDomainSnapshotCreateXML(virDomainPtr domain, if (!(def = virDomainSnapshotDefParseString(xmlDesc, privconn->caps, privconn->xmlopt, + NULL, parse_flags))) goto cleanup; diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index ac7e02eed6..2ca12a28e5 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -5502,7 +5502,7 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, NULL); if (!(def = virDomainSnapshotDefParseString(xmlDesc, data->caps, - data->xmlopt, + data->xmlopt, NULL, VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE))) goto cleanup; @@ -6948,7 +6948,7 @@ vboxDomainSnapshotDeleteMetadataOnly(virDomainSnapshotPtr snapshot) } def = virDomainSnapshotDefParseString(defXml, data->caps, - data->xmlopt, + data->xmlopt, NULL, VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); if (!def) { diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index 1bf6daf9b0..eba366dd2c 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -2618,7 +2618,8 @@ vzDomainSnapshotCreateXML(virDomainPtr domain, goto cleanup; if (!(def = virDomainSnapshotDefParseString(xmlDesc, driver->caps, - driver->xmlopt, parse_flags))) + driver->xmlopt, NULL, + parse_flags))) goto cleanup; if (def->ndisks > 0) { diff --git a/tests/domainsnapshotxml2xmltest.c b/tests/domainsnapshotxml2xmltest.c index 9eb71780fc..9f7f98585f 100644 --- a/tests/domainsnapshotxml2xmltest.c +++ b/tests/domainsnapshotxml2xmltest.c @@ -80,6 +80,7 @@ testCompareXMLToXMLFiles(const char *inxml, virDomainSnapshotDefPtr def = NULL; unsigned int parseflags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS; unsigned int formatflags = VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE; + bool cur; if (internal) { parseflags |= VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL; @@ -96,9 +97,11 @@ testCompareXMLToXMLFiles(const char *inxml, goto cleanup; if (!(def = virDomainSnapshotDefParseString(inXmlData, driver.caps, - driver.xmlopt, + driver.xmlopt, &cur, parseflags))) goto cleanup; + if (cur) + formatflags |= VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT; if (!(actual = virDomainSnapshotDefFormat(uuid, def, driver.caps, driver.xmlopt, -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list