Valid HTML 4.01 Transitional
Prev: How to Use the USB Video Capture Dongle Next: DHCP IPv6 Gets Pool Address, not Assigned IP
(Index)
Jim Carter's Bugfixes

EFI Booting a Virtual Machine with BTRFS Root

James F. Carter
2023-01-18
Symptom:

You have a virtual machine. (Mine is on KVM.) It has a BTRFS filesystem providing its root directory, a subvolume. It also needs to boot using EFI (Extensible Firmware Interface) rather than legacy BIOS.

I'm running OpenSuSE Tumbleweed, and the layout of the BTRFS goes like this:

I run the SuSE installer, and the resulting disc can be booted. I install and remove other packages and do other setup and customization steps. I sneeze. Now it won't boot. Grub claims it can't read font and theme files, nor can it read the kernel and initrd; for the latter it gave this error message:

Loading Linux 6.1.4-1-default
Error: ../../grub-core/fs/btrfs.c:2156: file '/@/boot/vmlinuz-6.1.4-1-default' not found

How do I recover, or, what could I have done to avoid breaking the bootloader.

What's happening:

Compare these mount commands.

losetup --find #prints /dev/loop0
losetup --partscan /dev/loop0 orion-disc1.raw
mount /dev/disk/by-label/ROOT-DRAGON /mnt #Wrong
mount /@/dev/disk/by-label/ROOT-DRAGON /mnt #Wronger
mount -o subvol=@ /dev/disk/by-label/ROOT-DRAGON /mnt #Correct

The one tagged wrong looks like it got the root partition, no error messages. /mnt/boot contains grub.cfg and the font and theme files that it ought to. /mnt/boot/vmlinuz points to vmlinuz-6.1.3-1-default which points to ../usr/lib/modules/6.1.3-1-default/vmlinuz which is a large, kernel-sized plain file. Looks good so far, but why won't the disc boot?

The one tagged wronger is seen at boot time; see below for how to fix this.

The one tagged correct mounts the root subvolume, which is where the content really is. Now we can reinstall the bootloader.

How to fix:

To un-sneeze, i.e. to make sure this problem is banished, look at /etc/default/grub in the mounted filesystem. It needs these control parameters set:

On the second item, I figured that I had not enabled snapshots, so I had better not turn that one on. Bad move! Basically, grub2-mkconfig runs all (or most?) filenames through a function make_system_path_relative_to_its_root which chops off the mount point of the partition containing the file. But on btrfs filesystems only, it prepends the subvolume path (rooted at /@ on SuSE). Grub at boot time cannot read such a path, with the result that after you rebuild /boot/grub2/grub.cfg (e.g. after getting a new kernel), the machine cannot boot. Except, if /etc/default/grub contains SUSE_BTRFS_SNAPSHOT_BOOTING="true", the -r option is added to the call to grub2-mkrelpath (from btrfsprogs package), which makes it behave like on other filesystem types, i.e. no prepended subvolume path.

Now, to reinstall the bootloader, go through these steps. Other distros actually have this scripted under the name arch-chroot, ubuntu-chroot, etc. Actually I do this often enough that it's worth it to write my own script; here it is. Beware, it has these idiosyncracies which definitely differ from stock SuSE as well as other distros:

The steps go like this:


Prev: How to Use the USB Video Capture Dongle Next: DHCP IPv6 Gets Pool Address, not Assigned IP
(Index)