[libvirt] [PATCHv1 5/5] qemu: add support for creating and using qcow3 images

Ján Tomko jtomko at redhat.com
Thu Jan 10 12:28:59 UTC 2013


QEMU uses the qcow2 driver for qcow3, which is why
virStorageFileFormatToStringQemu is added.

TODO: make snapshots work.
---
 src/libvirt_private.syms      |    1 +
 src/qemu/qemu_command.c       |    2 +-
 src/qemu/qemu_hotplug.c       |    4 ++--
 src/storage/storage_backend.c |   29 +++++++++++++++++++++++------
 src/util/virstoragefile.c     |    8 ++++++++
 src/util/virstoragefile.h     |    1 +
 6 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 699cec6..9193342 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1165,6 +1165,7 @@ virStorageGenerateQcowPassphrase;
 
 # storage_file.h
 virStorageFileChainLookup;
+virStorageFileFormatToStringQemu;
 virStorageFileFormatTypeFromString;
 virStorageFileFormatTypeToString;
 virStorageFileFreeMetadata;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 3e3b588..4c7451b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2417,7 +2417,7 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
         disk->type != VIR_DOMAIN_DISK_TYPE_DIR &&
         qemuCapsGet(caps, QEMU_CAPS_DRIVE_FORMAT))
         virBufferAsprintf(&opt, ",format=%s",
-                          virStorageFileFormatTypeToString(disk->format));
+                          virStorageFileFormatToStringQemu(disk->format));
 
     /* generate geometry command string */
     if (disk->geometry.cylinders > 0 &&
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 19172e1..305271b 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -109,9 +109,9 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
         const char *format = NULL;
         if (disk->type != VIR_DOMAIN_DISK_TYPE_DIR) {
             if (disk->format > 0)
-                format = virStorageFileFormatTypeToString(disk->format);
+                format = virStorageFileFormatToStringQemu(disk->format);
             else if (origdisk->format > 0)
-                format = virStorageFileFormatTypeToString(origdisk->format);
+                format = virStorageFileFormatToStringQemu(origdisk->format);
         }
         ret = qemuMonitorChangeMedia(priv->mon,
                                      driveAlias,
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index a7e9493..192c085 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -670,22 +670,23 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
     unsigned long long int size_arg;
     bool preallocate = false;
     char *options;
+    bool tmp;
     virBuffer buf = VIR_BUFFER_INITIALIZER;
 
     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
 
     preallocate = !!(flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA);
 
-    const char *type = virStorageFileFormatTypeToString(vol->target.format);
+    const char *type = virStorageFileFormatToStringQemu(vol->target.format);
     const char *backingType = vol->backingStore.path ?
-        virStorageFileFormatTypeToString(vol->backingStore.format) : NULL;
+        virStorageFileFormatToStringQemu(vol->backingStore.format) : NULL;
 
     const char *inputBackingPath = (inputvol ? inputvol->backingStore.path
                                              : NULL);
     const char *inputPath = inputvol ? inputvol->target.path : NULL;
     /* Treat input block devices as 'raw' format */
     const char *inputType = inputPath ?
-        virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ?
+        virStorageFileFormatToStringQemu(inputvol->type == VIR_STORAGE_VOL_BLOCK ?
                                          VIR_STORAGE_FILE_RAW :
                                          inputvol->target.format) :
         NULL;
@@ -702,9 +703,11 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
                        inputvol->target.format);
         return -1;
     }
-    if (preallocate && vol->target.format != VIR_STORAGE_FILE_QCOW2) {
+    if (preallocate && vol->target.format != VIR_STORAGE_FILE_QCOW2
+        && vol->target.format != VIR_STORAGE_FILE_QCOW3) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("metadata preallocation only available with qcow2"));
+                       _("metadata preallocation only available with qcow2"
+                         " or qcow3"));
         return -1;
     }
 
@@ -763,7 +766,8 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
         virStorageEncryptionPtr enc;
 
         if (vol->target.format != VIR_STORAGE_FILE_QCOW &&
-            vol->target.format != VIR_STORAGE_FILE_QCOW2) {
+            vol->target.format != VIR_STORAGE_FILE_QCOW2 &&
+            vol->target.format != VIR_STORAGE_FILE_QCOW3) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("qcow volume encryption unsupported with "
                              "volume format %s"), type);
@@ -831,6 +835,19 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
         else if (preallocate)
             virBufferAddLit(&buf, ",preallocation=metadata");
 
+        if (vol->target.format == VIR_STORAGE_FILE_QCOW3) {
+            virBufferAddLit(&buf, ",compat=1.1");
+            if (virBitmapGetBit(vol->target.features.compatible,
+                                VIR_STORAGE_FILE_QCOW3_COMP_LAZY_REFCOUNT,
+                                &tmp) < 0) {
+                virReportOOMError();
+                virBufferFreeAndReset(&buf);
+                goto cleanup;
+            }
+            if (tmp)
+                virBufferAddLit(&buf, ",lazy_refcounts=on");
+        }
+
         if (virBufferError(&buf) > 0) {
             virReportOOMError();
             goto cleanup;
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index e9ecff1..75518ab 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1493,3 +1493,11 @@ error:
         *meta = NULL;
     return NULL;
 }
+
+const char *virStorageFileFormatToStringQemu(enum virStorageFileFormat format)
+{
+    if (format == VIR_STORAGE_FILE_QCOW3)
+        return virStorageFileFormatTypeToString(VIR_STORAGE_FILE_QCOW2);
+    else
+        return virStorageFileFormatTypeToString(format);
+}
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index 3249e8f..8a010fa 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -131,5 +131,6 @@ int virStorageFileGetLVMKey(const char *path,
                             char **key);
 int virStorageFileGetSCSIKey(const char *path,
                              char **key);
+const char *virStorageFileFormatToStringQemu(enum virStorageFileFormat format);
 
 #endif /* __VIR_STORAGE_FILE_H__ */
-- 
1.7.8.6




More information about the libvir-list mailing list