[libvirt] [PATCH v2 6/6] qemu: add qcow3 support to external snapshots

Ján Tomko jtomko at redhat.com
Tue Feb 5 11:56:17 UTC 2013


---
 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




More information about the libvir-list mailing list