[libvirt] [PATCHv2 3/9] conf: restrict external snapshots to backing store formats

Eric Blake eblake at redhat.com
Mon Apr 14 22:54:14 UTC 2014


Domain snapshots should only permit an external snapshot into
a storage format that permits a backing chain, since the new
snapshot file necessarily must be backed by the existing file.
The C code for the qemu driver is a little bit stricter in
currently enforcing only qcow2 or qed, but at the XML parser
level, including virt-xml-validate, it is fairly easy to
enforce that a user can't request a 'raw' external snapshot.

* docs/schemas/storagecommon.rng (storageFormat): Split out...
(storageFormatBacking): ...new sublist.
* docs/schemas/domainsnapshot.rng (disksnapshotdriver): Use new
type.
* src/util/virstoragefile.h (virStorageFileFormat): Rearrange for
easier code management.
* src/util/virstoragefile.c (virStorageFileFormat, fileTypeInfo):
Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML): Use
new marker to limit selection of formats.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 docs/schemas/domainsnapshot.rng |  2 +-
 docs/schemas/storagecommon.rng  | 17 ++++++++++----
 src/conf/snapshot_conf.c        |  7 ++++--
 src/util/virstoragefile.c       | 51 ++++++++++++++++++++++-------------------
 src/util/virstoragefile.h       | 15 ++++++++----
 5 files changed, 55 insertions(+), 37 deletions(-)

diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng
index 824a186..644da90 100644
--- a/docs/schemas/domainsnapshot.rng
+++ b/docs/schemas/domainsnapshot.rng
@@ -184,7 +184,7 @@
       <element name='driver'>
         <optional>
           <attribute name='type'>
-            <ref name='storageFormat'/>
+            <ref name='storageFormatBacking'/>
           </attribute>
         </optional>
         <empty/>
diff --git a/docs/schemas/storagecommon.rng b/docs/schemas/storagecommon.rng
index 37b43c6..2d61abc 100644
--- a/docs/schemas/storagecommon.rng
+++ b/docs/schemas/storagecommon.rng
@@ -52,23 +52,30 @@
     </element>
   </define>

+  <!-- split the list of known storage formats into two, those where
+       we know how to follow backing chains, and all others -->
+  <define name='storageFormatBacking'>
+    <choice>
+      <value>cow</value>
+      <value>qcow</value>
+      <value>qcow2</value>
+      <value>qed</value>
+      <value>vmdk</value>
+    </choice>
+  </define>
   <define name='storageFormat'>
     <choice>
       <value>raw</value>
       <value>dir</value>
       <value>bochs</value>
       <value>cloop</value>
-      <value>cow</value>
       <value>dmg</value>
       <value>iso</value>
-      <value>qcow</value>
-      <value>qcow2</value>
-      <value>qed</value>
-      <value>vmdk</value>
       <value>vpc</value>
       <value>fat</value>
       <value>vhd</value>
       <value>vdi</value>
+      <ref name='storageFormatBacking'/>
     </choice>
   </define>

diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index 070e50d..b0e4700 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -158,9 +158,12 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
             char *driver = virXMLPropString(cur, "type");
             if (driver) {
                 def->src.format = virStorageFileFormatTypeFromString(driver);
-                if (def->src.format <= 0) {
+                if (def->src.format < VIR_STORAGE_FILE_BACKING) {
                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                   _("unknown disk snapshot driver '%s'"),
+                                   def->src.format <= 0
+                                   ? _("unknown disk snapshot driver '%s'")
+                                   : _("disk format '%s' lacks backing file "
+                                       "support"),
                                    driver);
                     VIR_FREE(driver);
                     goto cleanup;
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 94dddbc..42e9865 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -59,9 +59,10 @@ VIR_ENUM_IMPL(virStorageFileFormat,
               VIR_STORAGE_FILE_LAST,
               "none",
               "raw", "dir", "bochs",
-              "cloop", "cow", "dmg", "iso",
-              "qcow", "qcow2", "qed", "vmdk", "vpc",
-              "fat", "vhd", "vdi")
+              "cloop", "dmg", "iso",
+              "vpc", "fat", "vhd", "vdi",
+              /* Formats with backing file below here */
+              "cow", "qcow", "qcow2", "qed", "vmdk")

 VIR_ENUM_IMPL(virStorageFileFeature,
               VIR_STORAGE_FILE_FEATURE_LAST,
@@ -198,11 +199,6 @@ static struct FileTypeInfo const fileTypeInfo[] = {
         LV_LITTLE_ENDIAN, -1, {0},
         -1, 0, 0, -1, NULL, NULL
     },
-    [VIR_STORAGE_FILE_COW] = {
-        0, "OOOM", NULL,
-        LV_BIG_ENDIAN, 4, {2},
-        4+4+1024+4, 8, 1, -1, cowGetBackingStore, NULL
-    },
     [VIR_STORAGE_FILE_DMG] = {
         /* XXX QEMU says there's no magic for dmg,
          * /usr/share/misc/magic lists double magic (both offsets
@@ -216,6 +212,29 @@ static struct FileTypeInfo const fileTypeInfo[] = {
         LV_LITTLE_ENDIAN, -2, {0},
         -1, 0, 0, -1, NULL, NULL
     },
+    [VIR_STORAGE_FILE_VPC] = {
+        0, "conectix", NULL,
+        LV_BIG_ENDIAN, 12, {0x10000},
+        8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL, NULL
+    },
+    /* TODO: add getBackingStore function */
+    [VIR_STORAGE_FILE_VDI] = {
+        64, "\x7f\x10\xda\xbe", ".vdi",
+        LV_LITTLE_ENDIAN, 68, {0x00010001},
+        64 + 5 * 4 + 256 + 7 * 4, 8, 1, -1, NULL, NULL},
+
+    /* Not direct file formats, but used for various drivers */
+    [VIR_STORAGE_FILE_FAT] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
+                               -1, {0}, 0, 0, 0, 0, NULL, NULL },
+    [VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
+                               -1, {0}, 0, 0, 0, 0, NULL, NULL },
+
+    /* All formats with a backing store probe below here */
+    [VIR_STORAGE_FILE_COW] = {
+        0, "OOOM", NULL,
+        LV_BIG_ENDIAN, 4, {2},
+        4+4+1024+4, 8, 1, -1, cowGetBackingStore, NULL
+    },
     [VIR_STORAGE_FILE_QCOW] = {
         0, "QFI", NULL,
         LV_BIG_ENDIAN, 4, {1},
@@ -238,22 +257,6 @@ static struct FileTypeInfo const fileTypeInfo[] = {
         LV_LITTLE_ENDIAN, 4, {1, 2},
         4+4+4, 8, 512, -1, vmdk4GetBackingStore, NULL
     },
-    [VIR_STORAGE_FILE_VPC] = {
-        0, "conectix", NULL,
-        LV_BIG_ENDIAN, 12, {0x10000},
-        8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL, NULL
-    },
-    /* TODO: add getBackingStore function */
-    [VIR_STORAGE_FILE_VDI] = {
-        64, "\x7f\x10\xda\xbe", ".vdi",
-        LV_LITTLE_ENDIAN, 68, {0x00010001},
-        64 + 5 * 4 + 256 + 7 * 4, 8, 1, -1, NULL, NULL},
-
-    /* Not direct file formats, but used for various drivers */
-    [VIR_STORAGE_FILE_FAT] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
-                               -1, {0}, 0, 0, 0, 0, NULL, NULL },
-    [VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
-                               -1, {0}, 0, 0, 0, 0, NULL, NULL },
 };
 verify(ARRAY_CARDINALITY(fileTypeInfo) == VIR_STORAGE_FILE_LAST);

diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index 55ea890..29f93c1 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -64,18 +64,23 @@ enum virStorageFileFormat {
     VIR_STORAGE_FILE_DIR,
     VIR_STORAGE_FILE_BOCHS,
     VIR_STORAGE_FILE_CLOOP,
-    VIR_STORAGE_FILE_COW,
     VIR_STORAGE_FILE_DMG,
     VIR_STORAGE_FILE_ISO,
-    VIR_STORAGE_FILE_QCOW,
-    VIR_STORAGE_FILE_QCOW2,
-    VIR_STORAGE_FILE_QED,
-    VIR_STORAGE_FILE_VMDK,
     VIR_STORAGE_FILE_VPC,
     VIR_STORAGE_FILE_FAT,
     VIR_STORAGE_FILE_VHD,
     VIR_STORAGE_FILE_VDI,

+    /* Not a format, but a marker: all formats below this point have
+     * libvirt support for following a backing chain */
+    VIR_STORAGE_FILE_BACKING,
+
+    VIR_STORAGE_FILE_COW = VIR_STORAGE_FILE_BACKING,
+    VIR_STORAGE_FILE_QCOW,
+    VIR_STORAGE_FILE_QCOW2,
+    VIR_STORAGE_FILE_QED,
+    VIR_STORAGE_FILE_VMDK,
+
     VIR_STORAGE_FILE_LAST,
 };

-- 
1.9.0




More information about the libvir-list mailing list