[PATCH 3/5] conf: Introduce <metadata_cache> subelement of <disk><driver>

Peter Krempa pkrempa at redhat.com
Thu Jan 7 14:59:36 UTC 2021


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 at 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




More information about the libvir-list mailing list