[libvirt] [PATCH 2/3] xml: add disk driver metadata_cache_size option

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Thu Nov 1 11:32:23 UTC 2018


The only possible value is 'maximum' which makes l2_cache_size large
enough to keep all metadata in memory. This will unleash disks
performace for some database workloads and IO benchmarks with random
access to whole disk.

Note that imlementation sets l2-cache-size and not cache-size.
Both *cache-size's is upper limit on cache size value thus instead of
setting precise limit for disk which involves knowing disk size
and disk's cluster size we can just set INT64_MAX. Unfortunately
both old and new versions of qemu fail on setting cache-size to INT64_MAX.
Fortunately both old and new versions works well on such setting for
l2-cache-size. As guest performance depends only l2 cache size
and not refcount cache size (which is documented in recent qemu)
we can set l2 directly.

Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
---
 docs/formatdomain.html.in                          |  7 ++++
 docs/schemas/domaincommon.rng                      | 10 +++++
 src/conf/domain_conf.c                             | 17 ++++++++
 src/conf/domain_conf.h                             |  9 ++++
 src/qemu/qemu_command.c                            | 26 ++++++++++++
 src/qemu/qemu_domain.c                             |  1 +
 .../qemuxml2argvdata/disk-metadata_cache_size.args | 34 +++++++++++++++
 .../qemuxml2argvdata/disk-metadata_cache_size.xml  | 42 +++++++++++++++++++
 tests/qemuxml2argvtest.c                           |  2 +
 .../disk-metadata_cache_size.xml                   | 48 ++++++++++++++++++++++
 tests/qemuxml2xmltest.c                            |  2 +
 11 files changed, 198 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/disk-metadata_cache_size.args
 create mode 100644 tests/qemuxml2argvdata/disk-metadata_cache_size.xml
 create mode 100644 tests/qemuxml2xmloutdata/disk-metadata_cache_size.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8189959..93e0009 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3556,6 +3556,13 @@
             virt queues for virtio-blk. (<span class="since">Since 3.9.0</span>)
           </li>
           <li>
+            The optional <code>metadata_cache_size</code> attribute specifies
+            metadata cache size policy. The only possible value is "maximum" to
+            keep all metadata in cache, this will help if workload needs access
+            to whole disk all the time.  (<span class="since">Since
+            4.9.0</span>)
+          </li>
+          <li>
           For virtio disks,
           <a href="#elementsVirtio">Virtio-specific options</a> can also be
           set. (<span class="since">Since 3.5.0</span>)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 099a949..18efa3a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1990,6 +1990,9 @@
         <ref name="detect_zeroes"/>
       </optional>
       <optional>
+        <ref name="metadata_cache_size"/>
+      </optional>
+      <optional>
         <attribute name='queues'>
           <ref name="positiveInteger"/>
         </attribute>
@@ -2090,6 +2093,13 @@
       </choice>
     </attribute>
   </define>
+  <define name="metadata_cache_size">
+    <attribute name='metadata_cache_size'>
+      <choice>
+        <value>maximum</value>
+      </choice>
+    </attribute>
+  </define>
   <define name="controller">
     <element name="controller">
       <optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e8e0adc..04383f0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -885,6 +885,11 @@ VIR_ENUM_IMPL(virDomainDiskDetectZeroes, VIR_DOMAIN_DISK_DETECT_ZEROES_LAST,
               "on",
               "unmap")
 
+VIR_ENUM_IMPL(virDomainDiskMetadataCacheSize,
+              VIR_DOMAIN_DISK_METADATA_CACHE_SIZE_LAST,
+              "default",
+              "maximum")
+
 VIR_ENUM_IMPL(virDomainDiskMirrorState, VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
               "none",
               "yes",
@@ -9347,6 +9352,14 @@ virDomainDiskDefDriverParseXML(virDomainDiskDefPtr def,
     }
     VIR_FREE(tmp);
 
+    if ((tmp = virXMLPropString(cur, "metadata_cache_size")) &&
+        (def->metadata_cache_size = virDomainDiskMetadataCacheSizeTypeFromString(tmp)) <= 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("unknown driver metadata_cache_size value '%s'"), tmp);
+        goto cleanup;
+    }
+    VIR_FREE(tmp);
+
     ret = 0;
 
  cleanup:
@@ -23874,6 +23887,10 @@ virDomainDiskDefFormatDriver(virBufferPtr buf,
     if (disk->queues)
         virBufferAsprintf(&driverBuf, " queues='%u'", disk->queues);
 
+    if (disk->metadata_cache_size)
+        virBufferAsprintf(&driverBuf, " metadata_cache_size='%s'",
+                          virDomainDiskMetadataCacheSizeTypeToString(disk->metadata_cache_size));
+
     virDomainVirtioOptionsFormat(&driverBuf, disk->virtio);
 
     ret = virXMLFormatElement(buf, "driver", &driverBuf, NULL);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e30a4b2..b155058 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -568,6 +568,13 @@ typedef enum {
     VIR_DOMAIN_DISK_DETECT_ZEROES_LAST
 } virDomainDiskDetectZeroes;
 
+typedef enum {
+    VIR_DOMAIN_DISK_METADATA_CACHE_SIZE_DEFAULT = 0,
+    VIR_DOMAIN_DISK_METADATA_CACHE_SIZE_MAXIMUM,
+
+    VIR_DOMAIN_DISK_METADATA_CACHE_SIZE_LAST
+} virDomainDiskMetadataCacheSize;
+
 typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
 struct _virDomainBlockIoTuneInfo {
     unsigned long long total_bytes_sec;
@@ -672,6 +679,7 @@ struct _virDomainDiskDef {
     int discard; /* enum virDomainDiskDiscard */
     unsigned int iothread; /* unused = 0, > 0 specific thread # */
     int detect_zeroes; /* enum virDomainDiskDetectZeroes */
+    int metadata_cache_size; /* enum virDomainDiskMetadataCacheSize */
     char *domain_name; /* backend domain name */
     unsigned int queues;
     virDomainVirtioOptionsPtr virtio;
@@ -3388,6 +3396,7 @@ VIR_ENUM_DECL(virDomainDeviceSGIO)
 VIR_ENUM_DECL(virDomainDiskTray)
 VIR_ENUM_DECL(virDomainDiskDiscard)
 VIR_ENUM_DECL(virDomainDiskDetectZeroes)
+VIR_ENUM_DECL(virDomainDiskMetadataCacheSize)
 VIR_ENUM_DECL(virDomainDiskMirrorState)
 VIR_ENUM_DECL(virDomainController)
 VIR_ENUM_DECL(virDomainControllerModelPCI)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1ff593c..b33e6a5 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1330,6 +1330,21 @@ qemuCheckDiskConfig(virDomainDiskDefPtr disk,
         return -1;
     }
 
+    if (disk->metadata_cache_size &&
+        (disk->src->type != VIR_STORAGE_TYPE_FILE ||
+         disk->src->format != VIR_STORAGE_FILE_QCOW2)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("metadata_cache_size can only be set for qcow2 disks"));
+        return -1;
+    }
+
+    if (disk->metadata_cache_size &&
+        disk->metadata_cache_size != VIR_DOMAIN_DISK_METADATA_CACHE_SIZE_MAXIMUM) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("metadata_cache_size can only be set to 'maximum'"));
+        return -1;
+    }
+
     if (qemuCaps) {
         if (disk->serial &&
             disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
@@ -1353,6 +1368,14 @@ qemuCheckDiskConfig(virDomainDiskDefPtr disk,
                            _("detect_zeroes is not supported by this QEMU binary"));
             return -1;
         }
+
+        if (disk->metadata_cache_size &&
+            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_QCOW2_L2_CACHE_SIZE)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("setting metadata_cache_size is not supported by "
+                             "this QEMU binary"));
+            return -1;
+        }
     }
 
     if (disk->serial &&
@@ -1776,6 +1799,9 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
                           virDomainDiskIoTypeToString(disk->iomode));
     }
 
+    if (disk->metadata_cache_size == VIR_DOMAIN_DISK_METADATA_CACHE_SIZE_MAXIMUM)
+        virBufferAsprintf(&opt, ",l2-cache-size=%ld", INT64_MAX);
+
     qemuBuildDiskThrottling(disk, &opt);
 
     if (virBufferCheckError(&opt) < 0)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ba3fff6..896adf3 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -9074,6 +9074,7 @@ qemuDomainDiskChangeSupported(virDomainDiskDefPtr disk,
     /* "snapshot" is a libvirt internal field and thus can be changed */
     /* startupPolicy is allowed to be updated. Therefore not checked here. */
     CHECK_EQ(transient, "transient", true);
+    CHECK_EQ(metadata_cache_size, "metadata_cache_size", true);
 
     /* Note: For some address types the address auto generation for
      * @disk has still not happened at this point (e.g. driver
diff --git a/tests/qemuxml2argvdata/disk-metadata_cache_size.args b/tests/qemuxml2argvdata/disk-metadata_cache_size.args
new file mode 100644
index 0000000..5e67519
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-metadata_cache_size.args
@@ -0,0 +1,34 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name test \
+-S \
+-machine pc-0.13,accel=tcg,usb=off,dump-guest-core=off \
+-m 1024 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid 468404ad-d49c-40f2-9e14-02294f9c1be3 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-test/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot menu=on \
+-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \
+-usb \
+-drive file=/var/lib/libvirt/images/f14.img,format=qcow2,if=none,\
+id=drive-virtio-disk0,l2-cache-size=9223372036854775807 \
+-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,\
+id=virtio-disk0,bootindex=2 \
+-drive file=/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso,format=raw,if=none,\
+id=drive-ide0-1-0,media=cdrom,readonly=on \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,\
+bootindex=1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/disk-metadata_cache_size.xml b/tests/qemuxml2argvdata/disk-metadata_cache_size.xml
new file mode 100644
index 0000000..8ac2599
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-metadata_cache_size.xml
@@ -0,0 +1,42 @@
+<domain type='qemu'>
+  <name>test</name>
+  <uuid>468404ad-d49c-40f2-9e14-02294f9c1be3</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc-0.13'>hvm</type>
+    <boot dev='cdrom'/>
+    <boot dev='hd'/>
+    <bootmenu enable='yes'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu' type='qcow2' metadata_cache_size='maximum'/>
+      <source file='/var/lib/libvirt/images/f14.img'/>
+      <target dev='vda' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+    </disk>
+    <disk type='file' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='virtio-serial' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
+    </controller>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 39a7f1f..a0a2ff3 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -3044,6 +3044,8 @@ mymain(void)
     DO_TEST_CAPS_ARCH_LATEST("x86_64-pc-headless", "x86_64");
     DO_TEST_CAPS_ARCH_LATEST("x86_64-q35-headless", "x86_64");
 
+    DO_TEST("disk-metadata_cache_size", QEMU_CAPS_DRIVE_QCOW2_L2_CACHE_SIZE);
+
     if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
         virFileDeleteTree(fakerootdir);
 
diff --git a/tests/qemuxml2xmloutdata/disk-metadata_cache_size.xml b/tests/qemuxml2xmloutdata/disk-metadata_cache_size.xml
new file mode 100644
index 0000000..5fed22b
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/disk-metadata_cache_size.xml
@@ -0,0 +1,48 @@
+<domain type='qemu'>
+  <name>test</name>
+  <uuid>468404ad-d49c-40f2-9e14-02294f9c1be3</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc-0.13'>hvm</type>
+    <boot dev='cdrom'/>
+    <boot dev='hd'/>
+    <bootmenu enable='yes'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu' type='qcow2' metadata_cache_size='maximum'/>
+      <source file='/var/lib/libvirt/images/f14.img'/>
+      <target dev='vda' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+    </disk>
+    <disk type='file' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='virtio-serial' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
+    </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='0x03' function='0x0'/>
+    </memballoon>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 89640f6..c44e0fe 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1235,6 +1235,8 @@ mymain(void)
     DO_TEST("riscv64-virt",
             QEMU_CAPS_DEVICE_VIRTIO_MMIO);
 
+    DO_TEST("disk-metadata_cache_size", NONE);
+
     if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
         virFileDeleteTree(fakerootdir);
 
-- 
1.8.3.1




More information about the libvir-list mailing list