[libvirt PATCH 4/4] conf: add control over COW for storage pool directories

Daniel P. Berrangé berrange at redhat.com
Mon Jul 20 17:33:22 UTC 2020


The storage pool code now attempts to disable COW by default on btrfs,
but management applications may wish to override this behaviour. Thus we
introduce a concept of storage pool features:

  <features>
    <cow state='yes|no'/>
  </features>

If the <cow> feature policy is set, it will be enforced. It will always
return an hard error if COW cannot be explicitly set or unset.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 docs/formatstorage.html.in                   | 25 ++++++++++
 docs/schemas/storagepool.rng                 | 30 ++++++++++++
 src/conf/storage_conf.c                      | 49 ++++++++++++++++++++
 src/conf/storage_conf.h                      |  8 ++++
 src/storage/storage_util.c                   |  2 +-
 tests/storagepoolxml2xmlin/pool-dir-cow.xml  | 10 ++++
 tests/storagepoolxml2xmlout/pool-dir-cow.xml | 15 ++++++
 tests/storagepoolxml2xmltest.c               |  1 +
 8 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 tests/storagepoolxml2xmlin/pool-dir-cow.xml
 create mode 100644 tests/storagepoolxml2xmlout/pool-dir-cow.xml

diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index 2a7604d136..7493714c5c 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -67,6 +67,31 @@
         pool. <span class="since">Since 0.4.1</span></dd>
     </dl>
 
+    <h3><a id="StoragePoolFeatures">Features</a></h3>
+
+    <p>
+      Some pools support optional features:
+    </p>
+
+    <pre>
+...
+<features>
+  <cow state='no'>
+</features>
+...</pre>
+
+    <p>
+      Valid features are:
+    </p>
+    <ul>
+      <dd><code>cow</code></dd>
+      <dt>Controls whether the filesystem performs copy-on-write (COW) for
+        images in the pool. This may only be set for directory / filesystem
+        pools on the <code>btrfs</code> filesystem. If not set then libvirt
+        will attempt to disable COW on any btrfs filesystems.
+        <span class="since">Since 6.6.0</span>.</dt>
+    </ul>
+
     <h3><a id="StoragePoolSource">Source elements</a></h3>
 
     <p>
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index ff0d3c836c..f5cf6769c8 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -37,6 +37,7 @@
     <interleave>
       <ref name='commonmetadata'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcedir'/>
       <ref name='target'/>
     </interleave>
@@ -49,6 +50,7 @@
     <interleave>
       <ref name='commonmetadata'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcefs'/>
       <ref name='target'/>
     </interleave>
@@ -64,6 +66,7 @@
     <interleave>
       <ref name='commonmetadata'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcenetfs'/>
       <ref name='target'/>
     </interleave>
@@ -79,6 +82,7 @@
     <interleave>
       <ref name='commonMetadataNameOptional'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcelogical'/>
       <ref name='targetlogical'/>
     </interleave>
@@ -91,6 +95,7 @@
     <interleave>
       <ref name='commonmetadata'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcedisk'/>
       <ref name='target'/>
     </interleave>
@@ -103,6 +108,7 @@
     <interleave>
       <ref name='commonmetadata'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourceiscsi'/>
       <ref name='target'/>
     </interleave>
@@ -117,6 +123,7 @@
       <optional>
         <ref name='sizing'/>
       </optional>
+      <ref name='features'/>
       <ref name='sourceiscsidirect'/>
     </interleave>
   </define>
@@ -128,6 +135,7 @@
     <interleave>
       <ref name='commonmetadata'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcescsi'/>
       <ref name='target'/>
     </interleave>
@@ -140,6 +148,7 @@
     <interleave>
       <ref name='commonmetadata'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <optional>
         <ref name='sourcempath'/>
       </optional>
@@ -154,6 +163,7 @@
     <interleave>
       <ref name='commonMetadataNameOptional'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcerbd'/>
       <ref name='refresh'/>
     </interleave>
@@ -169,6 +179,7 @@
     <interleave>
       <ref name='commonMetadataNameOptional'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcesheepdog'/>
     </interleave>
   </define>
@@ -180,6 +191,7 @@
     <interleave>
       <ref name='commonMetadataNameOptional'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcegluster'/>
     </interleave>
   </define>
@@ -191,6 +203,7 @@
     <interleave>
       <ref name='commonMetadataNameOptional'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcezfs'/>
       <optional>
         <ref name='target'/>
@@ -205,6 +218,7 @@
     <interleave>
       <ref name='commonMetadataNameOptional'/>
       <ref name='sizing'/>
+      <ref name='features'/>
       <ref name='sourcevstorage'/>
       <ref name='target'/>
     </interleave>
@@ -277,6 +291,22 @@
     </interleave>
   </define>
 
+  <define name='features'>
+    <optional>
+      <element name='features'>
+        <interleave>
+          <optional>
+            <element name='cow'>
+              <attribute name="state">
+                <ref name='virYesNo'/>
+                </attribute>
+            </element>
+          </optional>
+        </interleave>
+      </element>
+    </optional>
+  </define>
+
   <define name='target'>
     <element name='target'>
       <interleave>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 65d9b33049..4e63865b39 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -839,6 +839,33 @@ virStoragePoolDefRefreshFormat(virBufferPtr buf,
 }
 
 
+static int
+virStoragePoolDefParseFeatures(virStoragePoolDefPtr def,
+                               xmlXPathContextPtr ctxt)
+{
+    g_autofree char *cow = virXPathString("string(./features/cow/@state)", ctxt);
+
+    if (cow) {
+        int val;
+        if (def->type != VIR_STORAGE_POOL_FS &&
+            def->type != VIR_STORAGE_POOL_DIR) {
+            virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                           _("cow feature may only be used for 'fs' and 'dir' pools"));
+            return -1;
+        }
+        if ((val = virTristateBoolTypeFromString(cow)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("invalid storage pool cow feature state '%s'"),
+                           cow);
+            return -1;
+        }
+        def->features.cow = val;
+    }
+
+    return 0;
+}
+
+
 virStoragePoolDefPtr
 virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
 {
@@ -910,6 +937,9 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
         }
     }
 
+    if (virStoragePoolDefParseFeatures(def, ctxt) < 0)
+        return NULL;
+
     if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
         if (!def->source.nhost) {
             virReportError(VIR_ERR_XML_ERROR, "%s",
@@ -1131,6 +1161,23 @@ virStoragePoolSourceFormat(virBufferPtr buf,
 }
 
 
+static void
+virStoragePoolDefFormatFeatures(virBufferPtr buf,
+                                virStoragePoolDefPtr def)
+{
+    if (!def->features.cow)
+        return;
+
+    virBufferAddLit(buf, "<features>\n");
+    virBufferAdjustIndent(buf, 2);
+    if (def->features.cow)
+        virBufferAsprintf(buf, "<cow state='%s'/>\n",
+                          virTristateBoolTypeToString(def->features.cow));
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</features>\n");
+}
+
+
 static int
 virStoragePoolDefFormatBuf(virBufferPtr buf,
                            virStoragePoolDefPtr def)
@@ -1166,6 +1213,8 @@ virStoragePoolDefFormatBuf(virBufferPtr buf,
     virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
                       def->available);
 
+    virStoragePoolDefFormatFeatures(buf, def);
+
     if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
         return -1;
 
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index daa21a127b..ffd406e093 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -180,6 +180,13 @@ struct _virStoragePoolSourceDevice {
     } geometry;
 };
 
+typedef struct _virStoragePoolFeatures virStoragePoolFeatures;
+typedef virStoragePoolFeatures *virStoragePoolFeaturesPtr;
+struct _virStoragePoolFeatures {
+    virTristateBool cow;
+};
+
+
 typedef struct _virStoragePoolSource virStoragePoolSource;
 typedef virStoragePoolSource *virStoragePoolSourcePtr;
 struct _virStoragePoolSource {
@@ -256,6 +263,7 @@ struct _virStoragePoolDef {
     unsigned long long capacity; /* bytes */
     unsigned long long available; /* bytes */
 
+    virStoragePoolFeatures features;
     virStoragePoolSource source;
     virStoragePoolTarget target;
 
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index 80b49bd1cf..f7c09e3375 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -2755,7 +2755,7 @@ virStorageBackendBuildLocal(virStoragePoolObjPtr pool)
         return -1;
 
     if (virFileSetCOW(def->target.path,
-                      VIR_TRISTATE_BOOL_ABSENT) < 0)
+                      def->features.cow) < 0)
         return -1;
 
     return 0;
diff --git a/tests/storagepoolxml2xmlin/pool-dir-cow.xml b/tests/storagepoolxml2xmlin/pool-dir-cow.xml
new file mode 100644
index 0000000000..2217f2b8e3
--- /dev/null
+++ b/tests/storagepoolxml2xmlin/pool-dir-cow.xml
@@ -0,0 +1,10 @@
+<pool type='dir'>
+  <name>vms</name>
+  <uuid>751f8e7e-d2e9-463d-8ffe-d38f5e13a19b</uuid>
+  <features>
+    <cow state="yes"/>
+  </features>
+  <target>
+    <path>/i/cant/believe/its/not/btrfs</path>
+  </target>
+</pool>
diff --git a/tests/storagepoolxml2xmlout/pool-dir-cow.xml b/tests/storagepoolxml2xmlout/pool-dir-cow.xml
new file mode 100644
index 0000000000..2f3fe1f909
--- /dev/null
+++ b/tests/storagepoolxml2xmlout/pool-dir-cow.xml
@@ -0,0 +1,15 @@
+<pool type='dir'>
+  <name>vms</name>
+  <uuid>751f8e7e-d2e9-463d-8ffe-d38f5e13a19b</uuid>
+  <capacity unit='bytes'>0</capacity>
+  <allocation unit='bytes'>0</allocation>
+  <available unit='bytes'>0</available>
+  <features>
+    <cow state='yes'/>
+  </features>
+  <source>
+  </source>
+  <target>
+    <path>/i/cant/believe/its/not/btrfs</path>
+  </target>
+</pool>
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
index 382a7c659f..f21f20357a 100644
--- a/tests/storagepoolxml2xmltest.c
+++ b/tests/storagepoolxml2xmltest.c
@@ -62,6 +62,7 @@ mymain(void)
 
     DO_TEST("pool-dir");
     DO_TEST("pool-dir-naming");
+    DO_TEST("pool-dir-cow");
     DO_TEST("pool-fs");
     DO_TEST("pool-logical");
     DO_TEST("pool-logical-nopath");
-- 
2.26.2




More information about the libvir-list mailing list