--- docs/formatsnapshot.html.in | 7 +++++ docs/schemas/domainsnapshot.rng | 4 +++ src/conf/snapshot_conf.c | 63 +++++++++++++++++++++++++++++++++++++++++ src/conf/snapshot_conf.h | 2 ++ src/qemu/qemu_driver.c | 21 +++++++++++--- 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in index 8fcc04c..842ebab 100644 --- a/docs/formatsnapshot.html.in +++ b/docs/formatsnapshot.html.in @@ -167,6 +167,13 @@ snapshots, the original file name becomes the read-only snapshot, and the new file name contains the read-write delta of all disk changes since the snapshot. + + An optional <code>features</code> element may be specified, + containing format-specific features. So far only for qcow3 + driver type. See + <a href="formatstorage.html#StorageVolTarget">storage volume + target</a> for valid values. <span class="since">Since 1.0.3 + </span> </dd> </dl> </dd> diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng index 45d55b5..7ceb582 100644 --- a/docs/schemas/domainsnapshot.rng +++ b/docs/schemas/domainsnapshot.rng @@ -6,6 +6,7 @@ </start> <include href='domaincommon.rng'/> + <include href='storagefeatures.rng'/> <define name='domainsnapshot'> <element name='domainsnapshot'> @@ -144,6 +145,9 @@ <empty/> </element> </optional> + <optional> + <ref name='diskFormatFeatures'/> + </optional> </interleave> </group> </choice> diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index fe77bd0..7be04f4 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -103,6 +103,35 @@ void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def) } static int +virDomainSnapshotDiskDefParseFeatures(xmlNodePtr node, + virDomainSnapshotDiskDefPtr def) +{ + int value; + xmlNodePtr cur; + + def->features = virBitmapNew(VIR_STORAGE_FILE_FEAT_QCOW3_LAST); + if (!def->features) + goto no_memory; + + for (cur = node->children; cur; cur = cur->next) { + if (cur->type != XML_ELEMENT_NODE) + continue; + value = virStorageFileFeaturesQcow3TypeFromString((const char*) + cur->name); + if (value >= 0 && virBitmapSetBit(def->features, value) < 0) + goto error; + } + + return 0; + +no_memory: + virReportOOMError(); +error: + virBitmapFree(def->features); + return -1; +} + +static int virDomainSnapshotDiskDefParseXML(xmlNodePtr node, virDomainSnapshotDiskDefPtr def) { @@ -146,6 +175,10 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node, goto cleanup; } VIR_FREE(driver); + } else if (!def->features && + xmlStrEqual(cur->name, BAD_CAST "features")) { + if (virDomainSnapshotDiskDefParseFeatures(cur, def) < 0) + goto cleanup; } } cur = cur->next; @@ -551,6 +584,30 @@ cleanup: return ret; } +static int +virDomainSnapshotDefFeaturesFormat(virBufferPtr buf, + int format, + virBitmapPtr features) +{ + int i; + bool tmp; + if (format != VIR_STORAGE_FILE_QCOW3) + return 0; + + virBufferAddLit(buf, "<features>\n"); + if (features) { + for (i = 0; i < VIR_STORAGE_FILE_FEAT_QCOW3_LAST; i++) { + if (virBitmapGetBit(features, i, &tmp) == 0 && tmp) { + virBufferEscapeString(buf, " <%s/>\n", + virStorageFileFeaturesQcow3TypeToString(i)); + } + } + } + virBufferAddLit(buf, "</features>\n"); + + return 0; +} + char *virDomainSnapshotDefFormat(const char *domain_uuid, virDomainSnapshotDefPtr def, unsigned int flags, @@ -602,6 +659,12 @@ char *virDomainSnapshotDefFormat(const char *domain_uuid, virBufferEscapeString(&buf, " <driver type='%s'/>\n", virStorageFileFormatTypeToString( disk->format)); + if (disk->format == VIR_STORAGE_FILE_QCOW3) { + virBufferAdjustIndent(&buf, 6); + virDomainSnapshotDefFeaturesFormat(&buf, disk->format, + disk->features); + virBufferAdjustIndent(&buf, -6); + } if (disk->file) virBufferEscapeString(&buf, " <source file='%s'/>\n", disk->file); diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h index f1d5995..7a8b08a 100644 --- a/src/conf/snapshot_conf.h +++ b/src/conf/snapshot_conf.h @@ -53,6 +53,8 @@ struct _virDomainSnapshotDiskDef { int snapshot; /* enum virDomainSnapshotLocation */ char *file; /* new source file when snapshot is external */ int format; /* enum virStorageFileFormat */ + virBitmapPtr features; /* format-specific features. + currently only used for qcow3 */ }; /* Stores the complete snapshot metadata */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 79f78fa..078d876 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10513,6 +10513,7 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver, virDomainDiskDefPtr defdisk; virCommandPtr cmd = NULL; const char *qemuImgPath; + const char *opts = NULL; virBitmapPtr created; int ret = -1; @@ -10541,16 +10542,25 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver, if (!(cmd = virCommandNewArgList(qemuImgPath, "create", "-f", - virStorageFileFormatTypeToString(snapdisk->format), + virStorageFileFormatToStringQemu(snapdisk->format), "-o", NULL))) goto cleanup; + if (snapdisk->format == VIR_STORAGE_FILE_QCOW3) { + opts = virStorageFileQemuImgQcow3Options(snapdisk->features); + if (!opts) + goto cleanup; + } else if (snapdisk->format == VIR_STORAGE_FILE_QCOW2) { + opts = strdup(",compat=0.10"); + } + if (defdisk->format > 0) { /* adds cmd line arg: backing_file=/path/to/backing/file,backing_fmd=format */ - virCommandAddArgFormat(cmd, "backing_file=%s,backing_fmt=%s", + virCommandAddArgFormat(cmd, "backing_file=%s,backing_fmt=%s%s", defdisk->src, - virStorageFileFormatTypeToString(defdisk->format)); + virStorageFileFormatToStringQemu(defdisk->format), + opts ? opts : ""); } else { if (!driver->allowDiskFormatProbing) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -10561,7 +10571,8 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver, } /* adds cmd line arg: backing_file=/path/to/backing/file */ - virCommandAddArgFormat(cmd, "backing_file=%s", defdisk->src); + virCommandAddArgFormat(cmd, "backing_file=%s%s", defdisk->src, + opts ? opts : ""); } /* adds cmd line args: /path/to/target/file */ @@ -10597,6 +10608,7 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver, ret = 0; cleanup: + VIR_FREE(opts); virCommandFree(cmd); /* unlink images if creation has failed */ @@ -10759,6 +10771,7 @@ qemuDomainSnapshotPrepare(virDomainObjPtr vm, virDomainSnapshotDefPtr def, if (!disk->format) { disk->format = VIR_STORAGE_FILE_QCOW2; } else if (disk->format != VIR_STORAGE_FILE_QCOW2 && + disk->format != VIR_STORAGE_FILE_QCOW3 && disk->format != VIR_STORAGE_FILE_QED) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("external snapshot format for disk %s " -- 1.7.12.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list