From: Daniel P. Berrangé Date: Fri, 17 Jul 2020 18:32:18 +0000 (+0100) Subject: conf: add control over COW for storage pool directories X-Git-Tag: v6.6.0-rc1~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bb8ccb050d17e6068a02a6e3c356391ba50269d7;p=thirdparty%2Flibvirt.git conf: add control over COW for storage pool directories 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: If the feature policy is set, it will be enforced. It will always return an hard error if COW cannot be explicitly set or unset. Reviewed-by: Neal Gompa Reviewed-by: Peter Krempa Reviewed-by: Michal Privoznik Signed-off-by: Daniel P. Berrangé --- 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. Since 0.4.1 +

Features

+ +

+ Some pools support optional features: +

+ +
+...
+<features>
+  <cow state='no'>
+</features>
+...
+ +

+ Valid features are: +

+
    +
    cow
    +
    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 btrfs filesystem. If not set then libvirt + will attempt to disable COW on any btrfs filesystems. + Since 6.6.0.
    +
+

Source elements

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 @@ + @@ -49,6 +50,7 @@ + @@ -64,6 +66,7 @@ + @@ -79,6 +82,7 @@ + @@ -91,6 +95,7 @@ + @@ -103,6 +108,7 @@ + @@ -117,6 +123,7 @@ + @@ -128,6 +135,7 @@ + @@ -140,6 +148,7 @@ + @@ -154,6 +163,7 @@ + @@ -169,6 +179,7 @@ + @@ -180,6 +191,7 @@ + @@ -191,6 +203,7 @@ + @@ -205,6 +218,7 @@ + @@ -277,6 +291,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 65d9b33049..fac5ff7b86 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 == VIR_TRISTATE_BOOL_ABSENT) + return; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + if (def->features.cow != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(buf, "\n", + virTristateBoolTypeToString(def->features.cow)); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); +} + + static int virStoragePoolDefFormatBuf(virBufferPtr buf, virStoragePoolDefPtr def) @@ -1166,6 +1213,8 @@ virStoragePoolDefFormatBuf(virBufferPtr buf, virBufferAsprintf(buf, "%llu\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 @@ + + vms + 751f8e7e-d2e9-463d-8ffe-d38f5e13a19b + + + + + /i/cant/believe/its/not/btrfs + + 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 @@ + + vms + 751f8e7e-d2e9-463d-8ffe-d38f5e13a19b + 0 + 0 + 0 + + + + + + + /i/cant/believe/its/not/btrfs + + 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");