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@xxxxxxxxxx> --- 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