A Fast Filesystem For My Cloud at Home: Mapped vs. VirtIO

As I store quite a lot of data on my Nextcloud at home, it was clear to me when setting-up my new virtualized system at home that I did not want to store the data in the virtual disk image that holds the system partition. If I ever need to migrate the VM or need to extend the storage space, the last thing I want to do is to fiddle with the system partition. KVM/Qemu offers a number of different ways to map additional storage into a virtual machine and surprisingly, the performance of the different options differ quite significantly!

Mapped I/O

mapped io filesystemThe first option I tried, which at first I thought was preferable, was to map the filesystem of a LUKS encrypted separate disk partition of the VM host into the virtual machine. The directory I created on the host for this would only be used by the Nextcloud virtual machine and thus I could ensure that the VM could only access this and no other data stored elsewhere on the host partition. When files are put into this directory they are visible on the host and also in the virtual machine. There are different mapping options that govern access rights on the host and on the VM. I found that the ‘mapped’ mode as shown in the filesystem info screenshot on the left worked best for me in terms of file system permissions. In a VM instance, a mapped directory is mounted as follows:

# In the shell
sudo mount testlabel /home/martin/share-test -t 9p -o trans=virtio

# In /etc/fstab
testlabel /etc/ssl/le-manual-certs 9p rw,sync,dirsync,realtime,noauto,x-systemd.automount 0 0

Things looked nice at first. Unfortunately it turned out that Nextcloud runs really slow, and I mean really slow, when the data directory is put there. The virtual device driver for the mapping does not seem to be very optimized. In other words, this was totally unsuitable for my Nextcloud needs. For other purposes, however, this method can be a good choice. For example, I chose to use this approach to share other data such as SSL certificates among virtual machines this way.

Virtual IO

Create new VirtIO storageAnother option of KVM/Qemu is to use virtual disk images. Like the system disk, a virtual disk is a single file on the host system that is used for emulating a disk inside a virtual machine. For a 100 GB disk in the VM, one creates a 100 GB file on the host, e.g. via the virt-manager GUI. In the GUI, the menu option is called ‘storage’ instead of ‘VirtIO disk’, which is a bit confusing at first. After a reboot of the VM, the new virtual disk becomes available as /dev/vdb and can be partitioned and formatted just like a physical disk:

sudo -s
fdisk /dev/vdb

--> n (create new partition), use all space (new, primary, take all)
 --> w (write)
 
mkfs -t ext4 /dev/vdb1

# Mount in the shell
mount /dev/vdb1 /nextcloud

# Mount in fstab
/dev/vdb1 /nextcloud ext4 relatime,errors=remount-ro 0 1

As the virtual disk has a fixed size, this approach is less flexible than the mapped IO described above. However, VirtIO storage performed blazingly fast with my Nextcloud installation so it became the natural choice.