The blockdev-snapshot-sync command only takes a format
but does not allow specifying the compat level or other features
that should be used.
Pre-create the qcow2 file ourselves and tell qemu to reuse it.
Note: the default compat level for qemu (and thus external snapshot
creation) is now 1.10 but libvirt's storage driver still uses 0.10.
After this patch, 0.10 will be the default for both.
---
src/qemu/qemu_driver.c | 11 ++++++++
src/storage/storage_backend.c | 66 +++++++++++++++++++++++++++++++++++++++++++
src/storage/storage_backend.h | 5 ++++
src/storage/storage_driver.c | 27 ++++++++++++++++++
src/storage/storage_driver.h | 4 +++
5 files changed, 113 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 921417c..4f14546 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14073,6 +14073,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
char *device = NULL;
char *source = NULL;
const char *formatStr = NULL;
+ const char *qemuImgPath = NULL;
int ret = -1, rc;
bool need_unlink = false;
@@ -14082,6 +14083,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
return -1;
}
+ if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
+ goto cleanup;
+
if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0)
goto cleanup;
@@ -14114,6 +14118,13 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr
driver,
goto cleanup;
}
need_unlink = true;
+ if (newDiskSrc->format == VIR_STORAGE_FILE_QCOW2) {
+ rc = virStorageFileCreateWithFormat(newDiskSrc,
+ source,
+ disk->src,
+ qemuImgPath);
+ reuse = true;
+ }
}
/* set correct security, cgroup and locking options on the new image */
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 4ecea88..9ffbc6e 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1079,6 +1079,72 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
return cmd;
}
+
+/* Create a qemu-img virCommand from the supplied binary path,
+ * StorageSource and path (translated for network drives
+ * supported by qemu-img)
+ */
+static virCommandPtr
+virStorageBackendCreateQemuImgCmdFromSource(virStorageSourcePtr src,
+ const char *path,
+ virStorageSourcePtr backingSrc,
+ const char *create_tool)
+{
+ virCommandPtr cmd = NULL;
+ struct _virStorageBackendQemuImgInfo info = {
+ .format = src->format,
+ .path = path,
+ .encryption = NULL,
+ .preallocate = false,
+ .compat = src->compat,
+ .features = src->features,
+ .nocow = src->nocow,
+ };
+ char *tmpstr = NULL;
+
+ info.backingFormat = backingSrc->format;
+ info.backingPath = backingSrc->path;
+
+ if (!(tmpstr = virBitmapFormat(info.features)))
+ return NULL;
+
+ VIR_DEBUG("creating file via qemu_img: format %s path %s compat %s features
%s",
+ virStorageFileFormatTypeToString(info.format),
+ info.path, info.compat, tmpstr);
+ VIR_DEBUG("... backing format %s backing path %s",
+ virStorageFileFormatTypeToString(info.backingFormat),
+ info.backingPath);
+
+ cmd = virStorageBackendCreateQemuImgCmd(create_tool,
+ QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT,
+ info);
+ return cmd;
+}
+
+
+int
+virStorageBackendCreateQemuImgFileFromSource(virStorageSourcePtr src,
+ const char *path,
+ virStorageSourcePtr backingSrc,
+ const char *create_tool)
+{
+ int ret = -1;
+ virCommandPtr cmd = NULL;
+
+ cmd = virStorageBackendCreateQemuImgCmdFromSource(src, path, backingSrc,
+ create_tool);
+ if (!cmd)
+ goto cleanup;
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+
static int
virStorageBackendCreateQemuImg(virConnectPtr conn,
virStoragePoolObjPtr pool,
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index bb1e8d8..c591845 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -249,6 +249,11 @@ virStorageFileBackendPtr virStorageFileBackendForType(int type, int
protocol);
virStorageFileBackendPtr virStorageFileBackendForTypeInternal(int type,
int protocol,
bool report);
+int
+virStorageBackendCreateQemuImgFileFromSource(virStorageSourcePtr src,
+ const char *path,
+ virStorageSourcePtr backingSrc,
+ const char *create_tool);
struct _virStorageFileBackend {
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 551a0ca..162e065 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -2725,6 +2725,33 @@ virStorageFileCreate(virStorageSourcePtr src)
return ret;
}
+/**
+ * virStorageFileCreate: Creates a storage file stub with the specified
+ * format
+ *
+ * @src: file structure pointing to the file
+ * @path: path to the file
+ * @backingSrc: file structure pointing to the backing file
+ * @create_tool: path to qemu-img
+ *
+ * Returns 0 on success, -2 if the function isn't supported by the backend,
+ * -1 on other failure. Errno is set in case of failure.
+ */
+int virStorageFileCreateWithFormat(virStorageSourcePtr src,
+ const char *path,
+ virStorageSourcePtr backingSrc,
+ const char *create_tool)
+{
+ if (!virStorageFileIsInitialized(src) ||
+ !src->drv->backend->storageFileCreate) {
+ errno = ENOSYS;
+ return -2;
+ }
+
+ return virStorageBackendCreateQemuImgFileFromSource(src, path, backingSrc,
+ create_tool);
+}
+
/**
* virStorageFileUnlink: Unlink storage file via storage driver
diff --git a/src/storage/storage_driver.h b/src/storage/storage_driver.h
index 4f28dc1..c9d943a 100644
--- a/src/storage/storage_driver.h
+++ b/src/storage/storage_driver.h
@@ -36,6 +36,10 @@ int virStorageFileInitAs(virStorageSourcePtr src,
void virStorageFileDeinit(virStorageSourcePtr src);
int virStorageFileCreate(virStorageSourcePtr src);
+int virStorageFileCreateWithFormat(virStorageSourcePtr src,
+ const char *path,
+ virStorageSourcePtr backingSrc,
+ const char *create_tool);
int virStorageFileUnlink(virStorageSourcePtr src);
int virStorageFileStat(virStorageSourcePtr src,
struct stat *stat);
--
2.0.5