diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index eb3055024d57574501cf579ea8be9790223e539a..02c1facdb0ff27596c93f4405628d40f86e61a5b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8281,6 +8281,7 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt, xmlNodePtr source; char *type = NULL; char *format = NULL; + char *idx = NULL; int ret = -1; if (!(ctxt->node = virXPathNode("./backingStore[*]", ctxt))) { @@ -8291,6 +8292,13 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt, if (VIR_ALLOC(backingStore) < 0) goto cleanup; + if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) && + (idx = virXMLPropString(ctxt->node, "index")) && + virStrToLong_uip(idx, NULL, 10, &backingStore->id) < 0) { + virReportError(VIR_ERR_XML_ERROR, _("invalid disk index '%s'"), idx); + goto cleanup; + } + if (!(type = virXMLPropString(ctxt->node, "type"))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing disk backing store type")); @@ -21910,8 +21918,7 @@ virDomainDiskSourceFormat(virBufferPtr buf, static int virDomainDiskBackingStoreFormat(virBufferPtr buf, virStorageSourcePtr backingStore, - const char *backingStoreRaw, - unsigned int idx) + const char *backingStoreRaw) { const char *type; const char *format; @@ -21938,8 +21945,10 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf, return -1; } - virBufferAsprintf(buf, "\n", - type, idx); + virBufferAsprintf(buf, "id != 0) + virBufferAsprintf(buf, " index='%u'", backingStore->id); + virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); virBufferAsprintf(buf, "\n", format); @@ -21947,8 +21956,7 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf, if (virDomainDiskSourceFormatInternal(buf, backingStore, 0, 0, true) < 0 || virDomainDiskBackingStoreFormat(buf, backingStore->backingStore, - backingStore->backingStoreRaw, - idx + 1) < 0) + backingStore->backingStoreRaw) < 0) return -1; virBufferAdjustIndent(buf, -2); @@ -22084,7 +22092,7 @@ virDomainDiskDefFormat(virBufferPtr buf, * persistent storage of backing chains is ready. */ if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) && virDomainDiskBackingStoreFormat(buf, def->src->backingStore, - def->src->backingStoreRaw, 1) < 0) + def->src->backingStoreRaw) < 0) return -1; virBufferEscapeString(buf, "\n", def->domain_name); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 36c9fae2b7a6acf36b5aa13f57ec5441b048e2d8..01992e0ae530e49e58a84d40ee72876428e7b75e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -14429,6 +14429,17 @@ qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver, } +static void +qemuDomainSnapshotUpdateDiskSourcesRenumber(virStorageSourcePtr src) +{ + virStorageSourcePtr next; + unsigned int idx = 1; + + for (next = src->backingStore; next; next = next->backingStore) + next->id = idx++; +} + + /** * qemuDomainSnapshotUpdateDiskSources: * @dd: snapshot disk data object @@ -14451,6 +14462,9 @@ qemuDomainSnapshotUpdateDiskSources(qemuDomainSnapshotDiskDataPtr dd, VIR_STEAL_PTR(dd->src->backingStore, dd->disk->src); VIR_STEAL_PTR(dd->disk->src, dd->src); + /* fix numbering of disks */ + qemuDomainSnapshotUpdateDiskSourcesRenumber(dd->disk->src); + if (dd->persistdisk) { VIR_STEAL_PTR(dd->persistsrc->backingStore, dd->persistdisk->src); VIR_STEAL_PTR(dd->persistdisk->src, dd->persistsrc); diff --git a/src/storage/storage_source.c b/src/storage/storage_source.c index bf47622372ab0e363710b0d5b2db2661768a4d58..864c69928fe6a5941ae7e159e62f729c866e799c 100644 --- a/src/storage/storage_source.c +++ b/src/storage/storage_source.c @@ -396,7 +396,8 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src, uid_t uid, gid_t gid, bool allow_probe, bool report_broken, - virHashTablePtr cycle) + virHashTablePtr cycle, + unsigned int depth) { int ret = -1; const char *uniqueName; @@ -474,7 +475,7 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src, if ((ret = virStorageFileGetMetadataRecurse(backingStore, parent, uid, gid, allow_probe, report_broken, - cycle)) < 0) { + cycle, depth + 1)) < 0) { if (report_broken) goto cleanup; @@ -489,6 +490,8 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src, ret = 0; cleanup: + if (src->backingStore) + src->backingStore->id = depth; VIR_FREE(buf); virStorageFileDeinit(src); virStorageSourceFree(backingStore); @@ -543,7 +546,7 @@ virStorageFileGetMetadata(virStorageSourcePtr src, } ret = virStorageFileGetMetadataRecurse(src, src, uid, gid, - allow_probe, report_broken, cycle); + allow_probe, report_broken, cycle, 1); virHashFree(cycle); return ret; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index de767193842b0d295d42a25694df719e23d0c3ab..f342e429b16fedaa1f322fcd902173d6f6d6bdc0 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -2030,6 +2030,7 @@ virStorageSourceCopy(const virStorageSource *src, if (VIR_ALLOC(ret) < 0) return NULL; + ret->id = src->id; ret->type = src->type; ret->protocol = src->protocol; ret->format = src->format; diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 74dee10f2f672a6bc25521280c821bfd0c1a647b..d3bafefc33b346b197e2d167fff0e0e273529854 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -227,6 +227,7 @@ typedef virStorageSource *virStorageSourcePtr; * IMPORTANT: When adding fields to this struct it's also necessary to add * appropriate code to the virStorageSourceCopy deep copy function */ struct _virStorageSource { + unsigned int id; /* backing chain identifier, 0 is unset */ int type; /* virStorageType */ char *path; int protocol; /* virStorageNetProtocol */