Preventing shared disk accidents with libvirt
My gaming setup involves a libvirt VM with some passthrough, mainly the GPU, but also sound and USB devices for example.
Another device that is passed through to the VM is my dedicated SSD, formatted in
Btrfs.
Why Btrfs? Because it's both natively supported by the Linux kernel, and by the
WinBtrfs project that brings its support to Windows. That means I can easily
share the same disk for casual gaming that just works™ on the Windows VM, casual gaming that just works™ on the Linux
host with native games, and for Wine/Proton experiments with the same data I use on Windows without duplicating
everything.
That's a setup I've use for years without problem, but a recent adventure proved me I needed to be more careful
something to prevent accidents from happening again. Imagine that for some reason it's the week-end, and you make some
experiments with Lutris and your GOG
library, then a bit later a friend asks you to come have some fun, and the proposed game is a popular one that is known
not to work with Wine/Proton. Then you'll just fire up the VM, play the game for the rest of
the evening, then shut down everything and go to bed.
But on the next day, when you just thought everything was fine and you could go play some more games again, you realize
that nothing works anymore, and that the Btrfs filesystem is completely corrupted because it was mounted two times in
parallel, by two autonomous systems that thought had authority on it. The problem is not that serious, because nothing
on that disk was really important, and to fix it you simply mkfs.btrfs
again, and re-install everything. But when
re-installing everything involves re-downloading half a Terabyte, you also realize that a simple safe-guard would
probably not be too much luxury to avoid further accidents, and that's what this article is about!
Fortunately, someone in the libvirt
team thought one day that it would be great to run custom scripts when some events
occurred in the VM lifetime, and the hooks were developed.
Long story short, to prevent the story above from happening again, I just put the script below in the following
executable file: /etc/libvirt/hooks/qemu
#!/bin/bash
if [ "$2" = "prepare" ]; then
if findmnt /data; then
umount /data
fi
fi
Now, I can completely forget to unmount my shared disk, it will automatically be unmounted before being passed through to the VM, and I won't have to re-download my game library ever again... famous last words