VM disk settings can make a large difference to I/O latency and data safety. This guide explains KVM disk performance options in libvirt: cache modes, I/O modes and iothreads, with safe defaults for production.
Before you start
- Root on a KVM host and a test VM you can restart.
- Benchmark before changing anything; see disk I/O benchmarking with fio.
- Use VirtIO disks; emulated IDE/SATA is slow regardless of tuning.
Cache modes
| Mode | Host page cache | Safety | Use |
|---|---|---|---|
none | Bypassed (O_DIRECT) | Safe; guest flushes honoured | Recommended default; required for live migration on shared storage |
writeback | Used for reads and writes | Safe if the guest issues flushes; data in host cache until flushed | Can be faster on slow storage |
writethrough | Reads cached, writes synchronous | Safe | Slow writes |
directsync | Bypassed, every write synchronous | Very safe | Slowest |
unsafe | Ignores flushes | Data loss on host crash | Throwaway test VMs only |
I/O modes
io='native': Linux AIO, efficient withcache='none'on raw devices or preallocated files.io='threads': a thread pool; works with any cache mode.io='io_uring': newer interface on recent kernels and QEMU, often the best choice when available.
Example disk definition
<disk type='block' device='disk'>
<driver name='qemu' type='raw' cache='none' io='native' discard='unmap' iothread='1'/>
<source dev='/dev/vg_vms/web01-disk0'/>
<target dev='vda' bus='virtio'/>
</disk>Add iothreads at the domain level:
<iothreads>2</iothreads>An iothread moves disk processing off the main QEMU thread, which helps busy disks and multi-disk VMs. For virtio-scsi, set the iothread on the controller instead.
Discard and TRIM
discard='unmap' lets the guest free unused blocks on thin storage (qcow2, LVM-thin, ZFS, Ceph). Inside the guest, enable the weekly trim timer: sudo systemctl enable --now fstrim.timer.
Other factors
- Storage backend matters most: NVMe beats SATA SSD beats HDD; see NVMe vs SSD vs HDD.
- Raw on LVM/ZFS avoids qcow2 metadata overhead; see qcow2 vs raw.
- Use
virtio-blkfor lowest latency orvirtio-scsifor many disks.
Measure
fio --name=randrw --filename=/root/fio.test --size=2G --rw=randrw --bs=4k --iodepth=32 --ioengine=libaio --direct=1 --runtime=60 --time_basedRun the same test inside the VM before and after a change, at a quiet time.
Frequently asked questions
Is writeback dangerous?
Not with modern guests that send flushes; data is safe after a flush. unsafe is the dangerous one.
Can I change cache mode live?
No, edit the XML and fully restart the VM.
Do VPS customers control this?
No, it is a host setting. Customers can enable fstrim and use efficient filesystems.
