[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 4/8] conf: add features to volume target XML



Add <features> and <compat> elements to volume target XML.

<compat> is a string which for qcow2 represents the QEMU version
it should be compatible with. Valid values are 0.10 and 1.1.
1.1 is implicit if the <features> element is present, otherwise
qemu-img default is used. 0.10 can be specified to explicitly
create older images after the qemu-img default changes.

<features> contains optional features, so far
<lazy_refcounts/> is available, which enables caching of reference
counters, improving performance for snapshots.
---
 docs/formatstorage.html.in                    | 19 +++++++
 docs/schemas/Makefile.am                      |  1 +
 docs/schemas/storagefilefeatures.rng          | 24 +++++++++
 docs/schemas/storagevol.rng                   |  7 +++
 libvirt.spec.in                               |  1 +
 mingw-libvirt.spec.in                         |  2 +
 src/conf/storage_conf.c                       | 76 ++++++++++++++++++++++++++-
 src/conf/storage_conf.h                       |  6 ++-
 src/libvirt_private.syms                      |  2 +
 src/storage/storage_backend_fs.c              | 10 ++++
 tests/storagevolxml2xmlin/vol-qcow2-1.1.xml   | 32 +++++++++++
 tests/storagevolxml2xmlin/vol-qcow2-lazy.xml  | 35 ++++++++++++
 tests/storagevolxml2xmlout/vol-qcow2-1.1.xml  | 33 ++++++++++++
 tests/storagevolxml2xmlout/vol-qcow2-lazy.xml | 35 ++++++++++++
 tests/storagevolxml2xmltest.c                 |  2 +
 15 files changed, 283 insertions(+), 2 deletions(-)
 create mode 100644 docs/schemas/storagefilefeatures.rng
 create mode 100644 tests/storagevolxml2xmlin/vol-qcow2-1.1.xml
 create mode 100644 tests/storagevolxml2xmlin/vol-qcow2-lazy.xml
 create mode 100644 tests/storagevolxml2xmlout/vol-qcow2-1.1.xml
 create mode 100644 tests/storagevolxml2xmlout/vol-qcow2-lazy.xml

diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index 9c3be67..a53ef00 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -334,6 +334,10 @@
             &lt;mode&gt;0744&lt;/mode&gt;
             &lt;label&gt;virt_image_t&lt;/label&gt;
           &lt;/permissions&gt;
+          &lt;compat&gt;1.1&lt;/compat&gt;
+          &lt;features&gt;
+            &lt;lazy_refcounts/&gt;
+          &lt;/features&gt;
         &lt;/target&gt;</pre>
 
     <dl>
@@ -362,6 +366,21 @@
         contains the MAC (eg SELinux) label string.
         <span class="since">Since 0.4.1</span>
       </dd>
+      <dt><code>compat</code></dt>
+      <dd>Specify compatibility level. So far, this is only used for
+        <code>type='qcow2'</code> volumes. Valid values are <code>0.10</code>
+        and <code>1.1</code> so far, specifying QEMU version the images should
+        be compatible with. If the <code>feature</code> element is present,
+        1.1 is used. If omitted, qemu-img default is used.
+        <span class="since">Since 1.0.6</span>
+      </dd>
+      <dt><code>features</code></dt>
+      <dd>Format-specific features. Only used for <code>qcow2</code> now.
+        Valid sub-elements are:
+        <code>&lt;lazy_refcounts/&gt;</code> - allow delayed reference
+        counter updates.
+        <span class="since">Since 1.0.6</span>
+      </dd>
     </dl>
 
     <h3><a name="StorageVolBacking">Backing store elements</a></h3>
diff --git a/docs/schemas/Makefile.am b/docs/schemas/Makefile.am
index 4413d9e..f964272 100644
--- a/docs/schemas/Makefile.am
+++ b/docs/schemas/Makefile.am
@@ -15,6 +15,7 @@ schema_DATA = \
 	nwfilter.rng \
 	secret.rng \
 	storageencryption.rng \
+	storagefilefeatures.rng \
 	storagepool.rng \
 	storagevol.rng
 
diff --git a/docs/schemas/storagefilefeatures.rng b/docs/schemas/storagefilefeatures.rng
new file mode 100644
index 0000000..96a1829
--- /dev/null
+++ b/docs/schemas/storagefilefeatures.rng
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!-- A Relax NG schema for the libvirt volume features XML format -->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0";
+    datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes";>
+
+  <define name='compat'>
+    <element name='compat'>
+      <data type='string'>
+        <param name='pattern'>[^,]+</param>
+      </data>
+    </element>
+  </define>
+  <define name='fileFormatFeatures'>
+    <element name='features'>
+      <interleave>
+        <optional>
+          <element name='lazy_refcounts'>
+            <empty/>
+          </element>
+        </optional>
+      </interleave>
+    </element>
+  </define>
+</grammar>
diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index ca8ce56..ba381c2 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -8,6 +8,7 @@
   </start>
 
   <include href='storageencryption.rng'/>
+  <include href='storagefilefeatures.rng'/>
 
 
   <define name='vol'>
@@ -111,6 +112,12 @@
       <optional>
         <ref name='encryption'/>
       </optional>
+      <optional>
+        <ref name='compat'/>
+      </optional>
+      <optional>
+        <ref name='fileFormatFeatures'/>
+      </optional>
     </element>
   </define>
 
diff --git a/libvirt.spec.in b/libvirt.spec.in
index bd889f3..4101de6 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1948,6 +1948,7 @@ fi
 %{_datadir}/libvirt/schemas/nwfilter.rng
 %{_datadir}/libvirt/schemas/secret.rng
 %{_datadir}/libvirt/schemas/storageencryption.rng
+%{_datadir}/libvirt/schemas/storagefilefeatures.rng
 %{_datadir}/libvirt/schemas/storagepool.rng
 %{_datadir}/libvirt/schemas/storagevol.rng
 
diff --git a/mingw-libvirt.spec.in b/mingw-libvirt.spec.in
index 9208329..aa39231 100644
--- a/mingw-libvirt.spec.in
+++ b/mingw-libvirt.spec.in
@@ -213,6 +213,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
 %{mingw32_datadir}/libvirt/schemas/nwfilter.rng
 %{mingw32_datadir}/libvirt/schemas/secret.rng
 %{mingw32_datadir}/libvirt/schemas/storageencryption.rng
+%{mingw32_datadir}/libvirt/schemas/storagefilefeatures.rng
 %{mingw32_datadir}/libvirt/schemas/storagepool.rng
 %{mingw32_datadir}/libvirt/schemas/storagevol.rng
 %dir %{mingw32_datadir}/libvirt/api/
@@ -273,6 +274,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
 %{mingw64_datadir}/libvirt/schemas/nwfilter.rng
 %{mingw64_datadir}/libvirt/schemas/secret.rng
 %{mingw64_datadir}/libvirt/schemas/storageencryption.rng
+%{mingw64_datadir}/libvirt/schemas/storagefilefeatures.rng
 %{mingw64_datadir}/libvirt/schemas/storagepool.rng
 %{mingw64_datadir}/libvirt/schemas/storagevol.rng
 %dir %{mingw64_datadir}/libvirt/api/
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index e21c39a..1f3b610 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -96,6 +96,8 @@ VIR_ENUM_IMPL(virStoragePoolSourceAdapterType,
 
 typedef const char *(*virStorageVolFormatToString)(int format);
 typedef int (*virStorageVolFormatFromString)(const char *format);
+typedef const char *(*virStorageVolFeatureToString)(int feature);
+typedef int (*virStorageVolFeatureFromString)(const char *feature);
 
 typedef const char *(*virStoragePoolFormatToString)(int format);
 typedef int (*virStoragePoolFormatFromString)(const char *format);
@@ -106,6 +108,9 @@ struct _virStorageVolOptions {
     int defaultFormat;
     virStorageVolFormatToString formatToString;
     virStorageVolFormatFromString formatFromString;
+    virStorageVolFeatureToString featureToString;
+    virStorageVolFeatureFromString featureFromString;
+    int featureLast;
 };
 
 /* Flags to indicate mandatory components in the pool source */
@@ -161,6 +166,9 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
             .defaultFormat = VIR_STORAGE_FILE_RAW,
             .formatFromString = virStorageVolumeFormatFromString,
             .formatToString = virStorageFileFormatTypeToString,
+            .featureFromString = virStorageFileFeatureTypeFromString,
+            .featureToString = virStorageFileFeatureTypeToString,
+            .featureLast = VIR_STORAGE_FILE_FEATURE_LAST,
         },
     },
     { .poolType = VIR_STORAGE_POOL_FS,
@@ -174,6 +182,9 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
             .defaultFormat = VIR_STORAGE_FILE_RAW,
             .formatFromString = virStorageVolumeFormatFromString,
             .formatToString = virStorageFileFormatTypeToString,
+            .featureFromString = virStorageFileFeatureTypeFromString,
+            .featureToString = virStorageFileFeatureTypeToString,
+            .featureLast = VIR_STORAGE_FILE_FEATURE_LAST,
         },
     },
     { .poolType = VIR_STORAGE_POOL_NETFS,
@@ -188,6 +199,9 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
             .defaultFormat = VIR_STORAGE_FILE_RAW,
             .formatFromString = virStorageVolumeFormatFromString,
             .formatToString = virStorageFileFormatTypeToString,
+            .featureFromString = virStorageFileFeatureTypeFromString,
+            .featureToString = virStorageFileFeatureTypeToString,
+            .featureLast = VIR_STORAGE_FILE_FEATURE_LAST,
         },
     },
     { .poolType = VIR_STORAGE_POOL_ISCSI,
@@ -295,6 +309,8 @@ virStorageVolDefFree(virStorageVolDefPtr def) {
     }
     VIR_FREE(def->source.extents);
 
+    VIR_FREE(def->target.compat);
+    virBitmapFree(def->target.features);
     VIR_FREE(def->target.path);
     VIR_FREE(def->target.perms.label);
     VIR_FREE(def->target.timestamps);
@@ -1216,6 +1232,8 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
     char *capacity = NULL;
     char *unit = NULL;
     xmlNodePtr node;
+    xmlNodePtr *nodes = NULL;
+    int i, n;
 
     options = virStorageVolOptionsForPoolType(pool->type);
     if (options == NULL)
@@ -1308,6 +1326,36 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
         VIR_FREE(format);
     }
 
+    ret->target.compat = virXPathString("string(./target/compat)", ctxt);
+    if (ret->target.compat && strchr(ret->target.compat, ',')) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("forbidden characters in 'compat' attribute"));
+        goto cleanup;
+    }
+
+    if (virXPathNode("./target/features", ctxt) && options->featureLast) {
+        if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
+            goto cleanup;
+
+        if (!ret->target.compat && VIR_STRDUP(ret->target.compat, "1.1") < 0)
+            goto cleanup;
+
+        if (!(ret->target.features = virBitmapNew(options->featureLast)))
+            goto no_memory;
+
+        for (i = 0; i < n; i++) {
+            int f = options->featureFromString((const char*)nodes[i]->name);
+
+            if (f < 0) {
+                virReportError(VIR_ERR_XML_ERROR, _("unsupported feature %s"),
+                               (const char*)nodes[i]->name);
+                goto cleanup;
+            }
+            ignore_value(virBitmapSetBit(ret->target.features, f));
+        }
+        VIR_FREE(nodes);
+    }
+
     if (virStorageDefParsePerms(ctxt, &ret->backingStore.perms,
                                 "./backingStore/permissions",
                                 DEFAULT_VOL_PERM_MODE) < 0)
@@ -1315,7 +1363,11 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
 
     return ret;
 
- cleanup:
+no_memory:
+    virReportOOMError();
+
+cleanup:
+    VIR_FREE(nodes);
     VIR_FREE(allocation);
     VIR_FREE(capacity);
     VIR_FREE(unit);
@@ -1443,6 +1495,28 @@ virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
         virBufferAdjustIndent(buf, -4);
     }
 
+    virBufferEscapeString(buf, "    <compat>%s</compat>\n", def->compat);
+
+    if (options->featureLast > 0 && def->features) {
+        int i;
+        bool b;
+        bool empty = virBitmapIsAllClear(def->features);
+
+        if (empty)
+            virBufferAddLit(buf, "    <features/>\n");
+        else
+            virBufferAddLit(buf, "    <features>\n");
+
+        for (i = 0; i < options->featureLast; i++) {
+            ignore_value(virBitmapGetBit(def->features, i, &b));
+            if (b)
+                virBufferAsprintf(buf, "      <%s/>\n",
+                                  options->featureToString(i));
+        }
+        if (!empty)
+            virBufferAddLit(buf, "    </features>\n");
+    }
+
     virBufferAsprintf(buf, "  </%s>\n", type);
 
     return 0;
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 567a4ac..f1df6b8 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -26,6 +26,7 @@
 
 # include "internal.h"
 # include "storage_encryption_conf.h"
+# include "virbitmap.h"
 # include "virthread.h"
 
 # include <libxml/tree.h>
@@ -90,8 +91,11 @@ struct _virStorageVolTarget {
     virStoragePerms perms;
     virStorageTimestampsPtr timestamps;
     int type; /* only used by disk backend for partition type */
-    /* Currently used only in virStorageVolDef.target, not in .backingstore. */
+    /* The next three are currently used only in .target,
+     * not in .backingstore. */
     virStorageEncryptionPtr encryption;
+    virBitmapPtr features;
+    char *compat;
 };
 
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cc734da..b8893d4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1789,6 +1789,8 @@ virSocketAddrSetPort;
 
 # util/virstoragefile.h
 virStorageFileChainLookup;
+virStorageFileFeatureTypeFromString;
+virStorageFileFeatureTypeToString;
 virStorageFileFormatTypeFromString;
 virStorageFileFormatTypeToString;
 virStorageFileFreeMetadata;
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 1379f17..8f32754 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -150,6 +150,16 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
          */
     }
 
+    virBitmapFree(target->features);
+    target->features = meta->features;
+    meta->features = NULL;
+
+    if (meta->compat) {
+        VIR_FREE(target->compat);
+        target->compat = meta->compat;
+        meta->compat = NULL;
+    }
+
     virStorageFileFreeMetadata(meta);
 
     return ret;
diff --git a/tests/storagevolxml2xmlin/vol-qcow2-1.1.xml b/tests/storagevolxml2xmlin/vol-qcow2-1.1.xml
new file mode 100644
index 0000000..e8df8b3
--- /dev/null
+++ b/tests/storagevolxml2xmlin/vol-qcow2-1.1.xml
@@ -0,0 +1,32 @@
+<volume>
+  <name>OtherDemo.img</name>
+  <key>/var/lib/libvirt/images/OtherDemo.img</key>
+  <source>
+  </source>
+  <capacity unit="G">5</capacity>
+  <allocation>294912</allocation>
+  <target>
+    <path>/var/lib/libvirt/images/OtherDemo.img</path>
+    <format type='qcow2'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+    <encryption format='qcow'>
+      <secret type='passphrase' uuid='e78d4b51-a2af-485f-b0f5-afca709a80f4'/>
+    </encryption>
+    <features/>
+  </target>
+  <backingStore>
+    <path>/var/lib/libvirt/images/BaseDemo.img</path>
+    <format type='raw'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+  </backingStore>
+</volume>
diff --git a/tests/storagevolxml2xmlin/vol-qcow2-lazy.xml b/tests/storagevolxml2xmlin/vol-qcow2-lazy.xml
new file mode 100644
index 0000000..336342a
--- /dev/null
+++ b/tests/storagevolxml2xmlin/vol-qcow2-lazy.xml
@@ -0,0 +1,35 @@
+<volume>
+  <name>OtherDemo.img</name>
+  <key>/var/lib/libvirt/images/OtherDemo.img</key>
+  <source>
+  </source>
+  <capacity unit="G">5</capacity>
+  <allocation>294912</allocation>
+  <target>
+    <path>/var/lib/libvirt/images/OtherDemo.img</path>
+    <format type='qcow2'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+    <encryption format='qcow'>
+      <secret type='passphrase' uuid='e78d4b51-a2af-485f-b0f5-afca709a80f4'/>
+    </encryption>
+    <compat>1.1</compat>
+    <features>
+      <lazy_refcounts/>
+    </features>
+  </target>
+  <backingStore>
+    <path>/var/lib/libvirt/images/BaseDemo.img</path>
+    <format type='raw'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+  </backingStore>
+</volume>
diff --git a/tests/storagevolxml2xmlout/vol-qcow2-1.1.xml b/tests/storagevolxml2xmlout/vol-qcow2-1.1.xml
new file mode 100644
index 0000000..454ac11
--- /dev/null
+++ b/tests/storagevolxml2xmlout/vol-qcow2-1.1.xml
@@ -0,0 +1,33 @@
+<volume>
+  <name>OtherDemo.img</name>
+  <key>(null)</key>
+  <source>
+  </source>
+  <capacity unit='bytes'>5368709120</capacity>
+  <allocation unit='bytes'>294912</allocation>
+  <target>
+    <path>/var/lib/libvirt/images/OtherDemo.img</path>
+    <format type='qcow2'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+    <encryption format='qcow'>
+      <secret type='passphrase' uuid='e78d4b51-a2af-485f-b0f5-afca709a80f4'/>
+    </encryption>
+    <compat>1.1</compat>
+    <features/>
+  </target>
+  <backingStore>
+    <path>/var/lib/libvirt/images/BaseDemo.img</path>
+    <format type='raw'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+  </backingStore>
+</volume>
diff --git a/tests/storagevolxml2xmlout/vol-qcow2-lazy.xml b/tests/storagevolxml2xmlout/vol-qcow2-lazy.xml
new file mode 100644
index 0000000..4e30ede
--- /dev/null
+++ b/tests/storagevolxml2xmlout/vol-qcow2-lazy.xml
@@ -0,0 +1,35 @@
+<volume>
+  <name>OtherDemo.img</name>
+  <key>(null)</key>
+  <source>
+  </source>
+  <capacity unit='bytes'>5368709120</capacity>
+  <allocation unit='bytes'>294912</allocation>
+  <target>
+    <path>/var/lib/libvirt/images/OtherDemo.img</path>
+    <format type='qcow2'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+    <encryption format='qcow'>
+      <secret type='passphrase' uuid='e78d4b51-a2af-485f-b0f5-afca709a80f4'/>
+    </encryption>
+    <compat>1.1</compat>
+    <features>
+      <lazy_refcounts/>
+    </features>
+  </target>
+  <backingStore>
+    <path>/var/lib/libvirt/images/BaseDemo.img</path>
+    <format type='raw'/>
+    <permissions>
+      <mode>0644</mode>
+      <owner>0</owner>
+      <group>0</group>
+      <label>unconfined_u:object_r:virt_image_t:s0</label>
+    </permissions>
+  </backingStore>
+</volume>
diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c
index 07c79c1..e87b016 100644
--- a/tests/storagevolxml2xmltest.c
+++ b/tests/storagevolxml2xmltest.c
@@ -110,6 +110,8 @@ mymain(void)
     DO_TEST("pool-dir", "vol-file");
     DO_TEST("pool-dir", "vol-file-backing");
     DO_TEST("pool-dir", "vol-qcow2");
+    DO_TEST("pool-dir", "vol-qcow2-1.1");
+    DO_TEST("pool-dir", "vol-qcow2-lazy");
     DO_TEST("pool-disk", "vol-partition");
     DO_TEST("pool-logical", "vol-logical");
     DO_TEST("pool-logical", "vol-logical-backing");
-- 
1.8.1.5


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]