For live external snapshots, the image creation is done by QEMU
and we can't pass the needed options.
---
docs/formatsnapshot.html.in | 5 ++++
src/qemu/qemu_driver.c | 72 +++++++++++++++++++++++++++++++++++----------
2 files changed, 62 insertions(+), 15 deletions(-)
diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in
index 76689cb..e160455 100644
--- a/docs/formatsnapshot.html.in
+++ b/docs/formatsnapshot.html.in
@@ -170,6 +170,11 @@
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>compat</code> and
<code>features</code>
+ elements may be specified to control format-specific
+ features. So far only for qcow2 and only for non-live
+ external snapshots.
</dd>
</dl>
</dd>
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b1630f8..b3e2683 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10873,6 +10873,44 @@ qemuDomainSnapshotCreateInactiveInternal(virQEMUDriverPtr
driver,
return qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-c", false);
}
+static int
+qemuDomainSnapshotCreateQemuImgOpts(char **opts,
+ const char *backing_file,
+ const char *backing_fmt,
+ const char *compat,
+ int format,
+ virBitmapPtr features)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool b;
+ int i;
+
+ virBufferEscapeString(&buf, "backing_file=%s,", backing_file);
+ virBufferEscapeString(&buf, "backing_fmt=%s,", backing_fmt);
+ virBufferEscapeString(&buf, "compat=%s,", compat);
+ if (features && format == VIR_STORAGE_FILE_QCOW2) {
+ if (!compat)
+ virBufferAddLit(&buf, "compat=1.1,");
+ for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
+ ignore_value(virBitmapGetBit(features, i, &b));
+ if (b)
+ virBufferAsprintf(&buf, "%s,",
+ virStorageFileFeatureTypeToString(i));
+ }
+ }
+
+ virBufferTrim(&buf, ",", -1);
+
+ if (virBufferError(&buf)) {
+ virBufferFreeAndReset(&buf);
+ virReportOOMError();
+ return -1;
+ }
+
+ *opts = virBufferContentAndReset(&buf);
+ return 0;
+}
+
/* The domain is expected to be locked and inactive. */
static int
qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
@@ -10888,6 +10926,8 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
virBitmapPtr created = NULL;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
int ret = -1;
+ char *opts = NULL;
+ const char *backing_fmt = NULL;
if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
goto cleanup;
@@ -10918,23 +10958,25 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr
driver,
NULL)))
goto cleanup;
- 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",
- defdisk->src,
-
virStorageFileFormatTypeToString(defdisk->format));
- } else {
- if (!cfg->allowDiskFormatProbing) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unknown image format of '%s' and "
- "format probing is disabled"),
- defdisk->src);
- goto cleanup;
- }
- /* adds cmd line arg: backing_file=/path/to/backing/file */
- virCommandAddArgFormat(cmd, "backing_file=%s", defdisk->src);
+ if (defdisk->format > 0) {
+ backing_fmt = virStorageFileFormatTypeToString(defdisk->format);
+ } else if (!cfg->allowDiskFormatProbing) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown image format of '%s' and "
+ "format probing is disabled"),
+ defdisk->src);
+ goto cleanup;
}
+ if (qemuDomainSnapshotCreateQemuImgOpts(&opts, defdisk->src,
+ backing_fmt,
+ snapdisk->compat,
+ snapdisk->format,
+ snapdisk->features) < 0)
+ goto cleanup;
+
+ virCommandAddArg(cmd, opts);
+ VIR_FREE(opts);
/* adds cmd line args: /path/to/target/file */
virCommandAddArg(cmd, snapdisk->file);
--
1.8.1.5