In certain specific cases it might be beneficial to be able to control
the metadata caching of storage image format drivers of a hypervisor.
Introduce XML machinery to set the maximum size of the metadata cache
which will be used by qemu's qcow2 driver.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
docs/formatdomain.rst | 43 ++++++++++++++
docs/schemas/domaincommon.rng | 20 ++++++-
src/conf/domain_conf.c | 51 ++++++++++++++--
src/util/virstoragefile.c | 1 +
src/util/virstoragefile.h | 2 +
.../qemuxml2argvdata/disk-metadata-cache.xml | 46 +++++++++++++++
.../disk-metadata-cache.x86_64-latest.xml | 58 +++++++++++++++++++
tests/qemuxml2xmltest.c | 1 +
8 files changed, 216 insertions(+), 6 deletions(-)
create mode 100644 tests/qemuxml2argvdata/disk-metadata-cache.xml
create mode 100644 tests/qemuxml2xmloutdata/disk-metadata-cache.x86_64-latest.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 1189795974..abf85064fa 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -2735,6 +2735,11 @@ paravirtualized driver is specified via the ``disk`` element.
``format``
The ``format`` element contains ``type`` attribute which specifies the
internal format of the backing store, such as ``raw`` or ``qcow2``.
+
+ The ``format`` element can contain ``metadata_cache`` subelement, which
+ has identical semantics to the identically named subelement of ``driver``
+ of a ``disk``.
+
``source``
This element has the same structure as the ``source`` element in ``disk``.
It specifies which file, device, or network location contains the data of
@@ -2947,6 +2952,44 @@ paravirtualized driver is specified via the ``disk`` element.
virtio-blk. ( :since:`Since 3.9.0` )
- For virtio disks, `Virtio-specific options <#elementsVirtio>`__ can also
be set. ( :since:`Since 3.5.0` )
+ - The optional ``metadata_cache`` subelement controls aspects related to the
+ format specific caching of storage image metadata. Note that this setting
+ applies only on the top level image; the identically named sublelement of
+ ``backingStore``'s ``format`` element can be used to specify cache
+ settings for the backing image.
+
+ :since:`Since 7.0.0` the maximum size of the metadata cache of ``qcow2``
+ format driver of the ``qemu`` hypervisor can be controlled via the
+ ``max_size`` subelement (see example below).
+
+ In the majority of cases the default configuration used by the hypervisor
+ is sufficient so modifying this setting should not be necessary. For
+ specifics on how the metadata cache of ``qcow2`` in ``qemu`` behaves refer
+ to the ``qemu``
+ `qcow2 cache docs
<
https://git.qemu.org/?p=qemu.git;a=blob;f=docs/qcow2-cache.txt>`__
+
+ **Example:**
+
+::
+
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'>
+ <metadata_cache>
+ <max_size unit='bytes'>1234</max_size>
+ </metadata_cache>
+ </driver>
+ <source file='/var/lib/libvirt/images/domain.qcow'/>
+ <backingStore type='file'>
+ <format type='qcow2'>
+ <metadata_cache>
+ <max_size unit='bytes'>1234</max_size>
+ </metadata_cache>
+ </format>
+ <source file='/var/lib/libvirt/images/snapshot.qcow'/>
+ <backingStore/>
+ </backingStore>
+ <target dev='vdd' bus='virtio'/>
+ </disk>
``backenddomain``
The optional ``backenddomain`` element allows specifying a backend domain
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 24b4994670..56946a621a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1600,7 +1600,15 @@
<attribute name="type">
<ref name="storageFormat"/>
</attribute>
- <empty/>
+ <optional>
+ <element name="metadata_cache">
+ <optional>
+ <element name="max_size">
+ <ref name="scaledInteger"/>
+ </element>
+ </optional>
+ </element>
+ </optional>
</element>
</define>
@@ -2245,7 +2253,15 @@
</attribute>
</optional>
<ref name="virtioOptions"/>
- <empty/>
+ <optional>
+ <element name="metadata_cache">
+ <optional>
+ <element name="max_size">
+ <ref name="scaledInteger"/>
+ </element>
+ </optional>
+ </element>
+ </optional>
</element>
</define>
<define name="driverFormat">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3e1dccb1b8..ddacc6443b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -8589,6 +8589,12 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,
if (!(backingStore = virDomainStorageSourceParseBase(type, format, idx)))
return -1;
+ if (virParseScaledValue("./format/metadata_cache/max_size", NULL,
+ ctxt,
+ &backingStore->metadataCacheMaxSize,
+ 1, ULLONG_MAX, false) < 0)
+ return -1;
+
/* backing store is always read-only */
backingStore->readonly = true;
@@ -8939,9 +8945,13 @@ virDomainDiskDefParseValidate(const virDomainDiskDef *def)
static int
virDomainDiskDefDriverParseXML(virDomainDiskDefPtr def,
- xmlNodePtr cur)
+ xmlNodePtr cur,
+ xmlXPathContextPtr ctxt)
{
g_autofree char *tmp = NULL;
+ VIR_XPATH_NODE_AUTORESTORE(ctxt)
+
+ ctxt->node = cur;
def->driverName = virXMLPropString(cur, "name");
@@ -9051,6 +9061,12 @@ virDomainDiskDefDriverParseXML(virDomainDiskDefPtr def,
return -1;
}
+ if (virParseScaledValue("./metadata_cache/max_size", NULL,
+ ctxt,
+ &def->src->metadataCacheMaxSize,
+ 1, ULLONG_MAX, false) < 0)
+ return -1;
+
return 0;
}
@@ -9207,7 +9223,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
if (virDomainVirtioOptionsParseXML(cur, &def->virtio) < 0)
return NULL;
- if (virDomainDiskDefDriverParseXML(def, cur) < 0)
+ if (virDomainDiskDefDriverParseXML(def, cur, ctxt) < 0)
return NULL;
} else if (!def->mirror &&
virXMLNodeNameEqual(cur, "mirror") &&
@@ -24050,6 +24066,8 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf,
{
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
+ g_auto(virBuffer) formatAttrBuf = VIR_BUFFER_INITIALIZER;
+ g_auto(virBuffer) formatChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
bool inactive = flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE;
virStorageSourcePtr backingStore = src->backingStore;
@@ -24077,8 +24095,22 @@ virDomainDiskBackingStoreFormat(virBufferPtr buf,
if (backingStore->id != 0)
virBufferAsprintf(&attrBuf, " index='%u'",
backingStore->id);
- virBufferAsprintf(&childBuf, "<format type='%s'/>\n",
+ virBufferAsprintf(&formatAttrBuf, " type='%s'",
virStorageFileFormatTypeToString(backingStore->format));
+
+ if (backingStore->metadataCacheMaxSize > 0) {
+ g_auto(virBuffer) metadataCacheChildBuf =
VIR_BUFFER_INIT_CHILD(&formatChildBuf);
+
+ virBufferAsprintf(&metadataCacheChildBuf,
+ "<max_size
unit='bytes'>%llu</max_size>\n",
+ backingStore->metadataCacheMaxSize);
+
+ virXMLFormatElement(&formatChildBuf, "metadata_cache", NULL,
&metadataCacheChildBuf);
+ }
+
+ virXMLFormatElement(&childBuf, "format", &formatAttrBuf,
&formatChildBuf);
+
+
if (virDomainDiskSourceFormat(&childBuf, backingStore, "source", 0,
false,
flags, false, false, xmlopt) < 0)
return -1;
@@ -24146,6 +24178,7 @@ virDomainDiskDefFormatDriver(virBufferPtr buf,
virDomainDiskDefPtr disk)
{
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
+ g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
virBufferEscapeString(&attrBuf, " name='%s'",
virDomainDiskGetDriver(disk));
@@ -24197,7 +24230,17 @@ virDomainDiskDefFormatDriver(virBufferPtr buf,
virDomainVirtioOptionsFormat(&attrBuf, disk->virtio);
- virXMLFormatElement(buf, "driver", &attrBuf, NULL);
+ if (disk->src->metadataCacheMaxSize > 0) {
+ g_auto(virBuffer) metadataCacheChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
+
+ virBufferAsprintf(&metadataCacheChildBuf,
+ "<max_size
unit='bytes'>%llu</max_size>\n",
+ disk->src->metadataCacheMaxSize);
+
+ virXMLFormatElement(&childBuf, "metadata_cache", NULL,
&metadataCacheChildBuf);
+ }
+
+ virXMLFormatElement(buf, "driver", &attrBuf, &childBuf);
}
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 3db85d8b89..f870657dd8 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -2216,6 +2216,7 @@ virStorageSourceCopy(const virStorageSource *src,
def->sslverify = src->sslverify;
def->readahead = src->readahead;
def->timeout = src->timeout;
+ def->metadataCacheMaxSize = src->metadataCacheMaxSize;
/* storage driver metadata are not copied */
def->drv = NULL;
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index 2452b967b2..205db1b997 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -321,6 +321,8 @@ struct _virStorageSource {
unsigned long long clusterSize; /* in bytes, 0 if unknown */
bool has_allocation; /* Set to true when provided in XML */
+ unsigned long long metadataCacheMaxSize; /* size of the metadata cache in bytes */
+
size_t nseclabels;
virSecurityDeviceLabelDefPtr *seclabels;
diff --git a/tests/qemuxml2argvdata/disk-metadata-cache.xml
b/tests/qemuxml2argvdata/disk-metadata-cache.xml
new file mode 100644
index 0000000000..d79f194eee
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-metadata-cache.xml
@@ -0,0 +1,46 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i386</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' cache='none'>
+ <metadata_cache>
+ <max_size>12345</max_size>
+ </metadata_cache>
+ </driver>
+ <source file='/tmp/QEMUGuest1.img'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' cache='none'/>
+ <source file='/tmp/QEMUGuest2.img'/>
+ <backingStore type='file'>
+ <format type='qcow2'>
+ <metadata_cache>
+ <max_size unit='kiB'>1024</max_size>
+ </metadata_cache>
+ </format>
+ <source file='/tmp/backing-store.qcow'/>
+ <backingStore/>
+ </backingStore>
+ <target dev='hdb' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='1'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/disk-metadata-cache.x86_64-latest.xml
b/tests/qemuxml2xmloutdata/disk-metadata-cache.x86_64-latest.xml
new file mode 100644
index 0000000000..7104151a10
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/disk-metadata-cache.x86_64-latest.xml
@@ -0,0 +1,58 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i386</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' cache='none'>
+ <metadata_cache>
+ <max_size unit='bytes'>12345</max_size>
+ </metadata_cache>
+ </driver>
+ <source file='/tmp/QEMUGuest1.img'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' cache='none'/>
+ <source file='/tmp/QEMUGuest2.img'/>
+ <backingStore type='file'>
+ <format type='qcow2'>
+ <metadata_cache>
+ <max_size unit='bytes'>1048576</max_size>
+ </metadata_cache>
+ </format>
+ <source file='/tmp/backing-store.qcow'/>
+ <backingStore/>
+ </backingStore>
+ <target dev='hdb' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='1'/>
+ </disk>
+ <controller type='usb' index='0' model='piix3-uhci'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x02' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index f8bca9f559..093fceea3e 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -294,6 +294,7 @@ mymain(void)
DO_TEST_CAPS_VER("disk-cache", "2.7.0");
DO_TEST_CAPS_VER("disk-cache", "2.12.0");
DO_TEST_CAPS_LATEST("disk-cache");
+ DO_TEST_CAPS_LATEST("disk-metadata-cache");
DO_TEST("disk-network-nbd", NONE);
DO_TEST("disk-network-iscsi", QEMU_CAPS_VIRTIO_SCSI,
QEMU_CAPS_SCSI_BLOCK);
--
2.29.2