Hi, all

I've been reading the QEMU documentation, the Libvirt documentation, as well as doing some testing and code investigation regarding disk cache modes.

In the Libvirt documentation, it is stated that the disk driver cache modes accepted are "default", "none", "writethrough", "writeback", "directsync" and "unsafe". Analyzing the code, we can see that this is somewhat reflected on the cache modes that QEMU documents on the -drive option (https://qemu-project.gitlab.io/qemu/system/invocation.html): https://github.com/libvirt/libvirt/blob/04c1f458313e9001f5a804a898408e1f4985262b/src/qemu/qemu_domain.c#L10020-L10028

However, the default option (when we do not define the "cache" option) is different from other options and does not seem to map to any option on the Qemu side. I see that, from testing and analyzing the code, if the default (not defining the "cache" options) is used, cache.direct and cache.no-flush are not informed; also, the write-cache option is not informed.

Just for comparison, here is a disk defined with cache=writeback:

XML:

<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2' cache='writeback'/>
      <source file='/mnt/a66f48f5-13c6-3676-b320-a15d32bbf32f/c0e925a9-6697-4ee9-8abf-d36c7a95cea4' index='2'/>
      <backingStore type='file' index='3'>
        <format type='qcow2'/>
        <source file='/mnt/a66f48f5-13c6-3676-b320-a15d32bbf32f/0db52809-9f33-43ac-8151-5452e9dee330'/>
        <backingStore/>
      </backingStore>
      <target dev='vda' bus='virtio'/>
      <serial>c0e925a966974ee98abf</serial>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </disk>

Generated QEMU command:

-blockdev {"driver":"file","filename":"/mnt/a66f48f5-13c6-3676-b320-a15d32bbf32f/c0e925a9-6697-4ee9-8abf-d36c7a95cea4","node-name":"libvirt-2-storage","cache":{"direct":false,"no-flush":false},"auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-2-format","read-only":false,"cache":{"direct":false,"no-flush":false},"driver":"qcow2","file":"libvirt-2-storage","backing":"libvirt-3-format"} -device virtio-blk-pci,bus=pci.0,addr=0x5,drive=libvirt-2-format,id=virtio-disk0,bootindex=2,write-cache=on,serial=c0e925a966974ee98abf

And here is a disk that does not have the cache option:

XML:

<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/mnt/b59eff0f-5b97-37ed-a513-9e1983d1d19b/b430296b-0924-412e-a7b1-ddc3d4c90f83' index='2'/>
      <backingStore/>
      <target dev='vdc' bus='virtio'/>
      <serial>b430296b0924412ea7b1</serial>
      <alias name='virtio-disk2'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>

Generated QEMU command:

blockdev {"driver":"file","filename":"/mnt/b59eff0f-5b97-37ed-a513-9e1983d1d19b/b430296b-0924-412e-a7b1-ddc3d4c90f83","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-2-format","read-only":false,"driver":"qcow2","file":"libvirt-2-storage","backing":null} -device virtio-blk-pci,bus=pci.0,addr=0x8,drive=libvirt-2-format,id=virtio-disk2,serial=b430296b0924412ea7b1

The QEMU documentation states in the -drive option that the default cache mode is Writeback (see https://qemu-project.gitlab.io/qemu/system/invocation.html), so I expected that setting Writeback or Default as the cache mode on Libvirt would also be the same. I ran some performance tests using both options to try and verify if they were the same, but they are clearly different. For each of the configuration profiles below, I created a VM and ran some fio tests:

Combination Disk cache mode Disk Controller IO thread IO policy
hds0i default virtio-scsi 0 iouring
hds0t default virtio-scsi 0 threads
hds1i default virtio-scsi 1 iouring
hds1t default virtio-scsi 1 threads
hdv0i default virtio 0 iouring
hdv0t default virtio 0 threads
hdv1i default virtio 1 iouring
hdv1t default virtio 1 threads
wbs0i writeback virtio-scsi 0 iouring
wbs0t writeback virtio-scsi 0 threads
wbs1i writeback virtio-scsi 1 iouring
wbs1t writeback virtio-scsi 1 threads
wbv0i writeback virtio 0 iouring
wbv0t writeback virtio 0 threads
wbv1i writeback virtio 1 iouring
wbv1t writeback virtio 1 threads

The fio test results are in a html attached to the email.

I would like to understand what the practical difference is between not informing the cache and any other option. I can see that the disk is defined in different way, but just by analyzing the code I was not able to understand what that leads to; also, looking at the performance tests, we clearly see a difference in the results. Would anyone be able to explain what is the expected behavior when the disk is defined in such a way?

By the way, I'm using Libvirt 8.0.0 and Qemu 6.2.0.

Best regards,

João Jandre