[libvirt] [PATCH libvirt] storage: add preallocation element

Marc-André Lureau marcandre.lureau at gmail.com
Thu May 17 21:35:39 UTC 2012


Allow to specify preallocation mode for QCOW2 images.
If not specified or not available, it's ignored.

This change only modify the schema, doc, parsing and tests.
---
 docs/formatstorage.html.in               |    7 +++++++
 docs/schemas/storagevol.rng              |   18 ++++++++++++++++++
 src/conf/storage_conf.c                  |   26 ++++++++++++++++++++++++++
 src/conf/storage_conf.h                  |    1 +
 src/util/storage_file.c                  |    4 ++++
 src/util/storage_file.h                  |   10 ++++++++++
 tests/storagevolxml2xmlin/vol-qcow2.xml  |    1 +
 tests/storagevolxml2xmlout/vol-qcow2.xml |    1 +
 8 files changed, 68 insertions(+)

diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index d0e4319..232bd76 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -213,6 +213,7 @@
         <key>/var/lib/xen/images/sparse.img</key>
         <allocation>0</allocation>
         <capacity unit="T">1</capacity>
+        <preallocation mode="metadata"/>
         ...</pre>
 
     <dl>
@@ -252,6 +253,12 @@
         1,152,921,504,606,846,976 bytes).  <span class="since">Since
         0.4.1, multi-character <code>unit</code> since
         0.9.11</span></dd>
+      <dt><code>preallocation</code></dt>
+      <dd>An image with preallocated metadata is initially larger but
+        can improve performance when the image needs to grow. This is
+        supported by the QCOW2 image format.
+        Attribute <code>mode</code> value can be 'off' or 'metadata'.
+        <span class="since">Since 0.9.13</span></dd>
       <dt><code>capacity</code></dt>
       <dd>Providing the logical capacity for the volume. This value is
         in bytes by default, but a <code>unit</code> attribute can be
diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index 8edb877..b54db13 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -40,6 +40,9 @@
         <ref name='scaledInteger'/>
       </element>
     </optional>
+    <optional>
+      <ref name='preallocation'/>
+    </optional>
   </define>
 
   <define name='permissions'>
@@ -171,6 +174,21 @@
     </optional>
   </define>
 
+  <define name='preallocationmode'>
+    <choice>
+      <value>off</value>
+      <value>metadata</value>
+    </choice>
+  </define>
+
+  <define name='preallocation'>
+    <element name='preallocation'>
+      <attribute name='mode'>
+        <ref name='preallocationmode'/>
+      </attribute>
+    </element>
+  </define>
+
   <define name='name'>
     <data type='string'>
       <param name="pattern">[a-zA-Z0-9_\+\-\.]+</param>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 188af6d..f0a036b 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -992,6 +992,7 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
     char *allocation = NULL;
     char *capacity = NULL;
     char *unit = NULL;
+    char *preallocation = NULL;
     xmlNodePtr node;
 
     options = virStorageVolOptionsForPoolType(pool->type);
@@ -1036,6 +1037,18 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
         ret->allocation = ret->capacity;
     }
 
+    preallocation = virXPathString("string(./preallocation/@mode)", ctxt);
+    if (preallocation) {
+        if ((ret->preallocation = virStoragePreallocationModeTypeFromString(preallocation)) < 0) {
+            virStorageReportError(VIR_ERR_XML_ERROR,
+                                  _("unknown preallocation mode %s"), preallocation);
+            goto cleanup;
+        }
+        VIR_FREE(preallocation);
+    } else {
+        ret->preallocation = VIR_STORAGE_PREALLOCATION_DEFAULT;
+    }
+
     ret->target.path = virXPathString("string(./target/path)", ctxt);
     if (options->formatFromString) {
         char *format = virXPathString("string(./target/format/@type)", ctxt);
@@ -1091,6 +1104,7 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
     return ret;
 
  cleanup:
+    VIR_FREE(preallocation);
     VIR_FREE(allocation);
     VIR_FREE(capacity);
     VIR_FREE(unit);
@@ -1245,6 +1259,18 @@ virStorageVolDefFormat(virStoragePoolDefPtr pool,
     virBufferAsprintf(&buf,"  <allocation unit='bytes'>%llu</allocation>\n",
                       def->allocation);
 
+    if (def->preallocation != VIR_STORAGE_PREALLOCATION_DEFAULT) {
+        const char *preallocation;
+
+        preallocation = virStoragePreallocationModeTypeToString(def->preallocation);
+        if (!preallocation) {
+            virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+                                  "%s", _("unexpected preallocation mode"));
+            goto cleanup;
+        }
+        virBufferAsprintf(&buf,"  <preallocation mode='%s'/>\n", preallocation);
+    }
+
     if (virStorageVolTargetDefFormat(options, &buf,
                                      &def->target, "target") < 0)
         goto cleanup;
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 9222c4a..c7c7af0 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -98,6 +98,7 @@ struct _virStorageVolDef {
     virStorageVolSource source;
     virStorageVolTarget target;
     virStorageVolTarget backingStore;
+    int preallocation; /* virStoragePreallocationMode enum */
 };
 
 typedef struct _virStorageVolDefList virStorageVolDefList;
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index 530071e..63abe65 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -47,6 +47,10 @@ VIR_ENUM_IMPL(virStorageFileFormat,
               "cloop", "cow", "dmg", "iso",
               "qcow", "qcow2", "qed", "vmdk", "vpc")
 
+VIR_ENUM_IMPL(virStoragePreallocationMode,
+              VIR_STORAGE_PREALLOCATION_LAST,
+              "default", "off", "metadata")
+
 enum lv_endian {
     LV_LITTLE_ENDIAN = 1, /* 1234 */
     LV_BIG_ENDIAN         /* 4321 */
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
index 13d0e87..3e08163 100644
--- a/src/util/storage_file.h
+++ b/src/util/storage_file.h
@@ -46,6 +46,16 @@ enum virStorageFileFormat {
 
 VIR_ENUM_DECL(virStorageFileFormat);
 
+enum virStoragePreallocationMode {
+    VIR_STORAGE_PREALLOCATION_DEFAULT,
+    VIR_STORAGE_PREALLOCATION_OFF,
+    VIR_STORAGE_PREALLOCATION_METADATA,
+
+    VIR_STORAGE_PREALLOCATION_LAST
+};
+
+VIR_ENUM_DECL(virStoragePreallocationMode);
+
 typedef struct _virStorageFileMetadata {
     char *backingStore;
     int backingStoreFormat;
diff --git a/tests/storagevolxml2xmlin/vol-qcow2.xml b/tests/storagevolxml2xmlin/vol-qcow2.xml
index b4924de..b4c6522 100644
--- a/tests/storagevolxml2xmlin/vol-qcow2.xml
+++ b/tests/storagevolxml2xmlin/vol-qcow2.xml
@@ -5,6 +5,7 @@
   </source>
   <capacity unit="G">5</capacity>
   <allocation>294912</allocation>
+  <preallocation mode='metadata'/>
   <target>
     <path>/var/lib/libvirt/images/OtherDemo.img</path>
     <format type='qcow2'/>
diff --git a/tests/storagevolxml2xmlout/vol-qcow2.xml b/tests/storagevolxml2xmlout/vol-qcow2.xml
index 4490931..311c52e 100644
--- a/tests/storagevolxml2xmlout/vol-qcow2.xml
+++ b/tests/storagevolxml2xmlout/vol-qcow2.xml
@@ -5,6 +5,7 @@
   </source>
   <capacity unit='bytes'>5368709120</capacity>
   <allocation unit='bytes'>294912</allocation>
+  <preallocation mode='metadata'/>
   <target>
     <path>/var/lib/libvirt/images/OtherDemo.img</path>
     <format type='qcow2'/>
-- 
1.7.10.1




More information about the libvir-list mailing list