[Pkg-raspi-maintainers] Bug#984691: /etc/kernel/postinst.d/z50-raspi-firmware: generated cmdline.txt root parameter broken when using Btrfs
João Ricardo Sares Teles de Matos
joao.r.matos at tecnico.ulisboa.pt
Sun Mar 7 07:14:30 GMT 2021
Package: raspi-firmware
Version: 1.20210111+ds-2
Severity: important
File: /etc/kernel/postinst.d/z50-raspi-firmware
Dear Maintainer,
(Note: a solution is provided below)
When using a Btrfs filesystem as /, the root= parameter generated by the
z50-raspi-firmware script is incorrect due to the output of findmnt, as
used on line 52.
# findmnt -n --output=source /
/dev/mapper/raspberry-btrfs[/bullseye/root/@]
This can be somewhat corrected with the --nofsroot flag:
# findmnt -n --output=source --nofsroot /
/dev/mapper/raspberry-btrfs
I wrote "somewhat" because Btrfs filesystems can span multiple devices
and should therefore be referenced by UUID.
The part inside the square brackets above (/bullseye/root/@) is the
btrfs subvolume, which is passed in an additional cmdline parameter:
rootflags=subvol=/bullseye/root/@
It's also possible to reference the subvolume by ID, but I'm unfamiliar
with the use cases for that:
rootflags=subvolid=324
-- Scope
This bug should cause any Raspberry Pi system with a Btrfs root
filesystem to be unable to boot whenever cmdline.txt is re-generated by
z50-raspi-firmware, unless the workaround mentioned below is used.
-- Rescue
If this bug renders a system unbootable, you can either edit the
cmdline.txt file on another system or manually mount the root filesystem
on /root using the initramfs emergency shell, which is currently
available by default via the serial terminal.
-- Workaround
I'm working around this problem by configuring ROOTPART in
/etc/default/raspi-firmware, as such:
ROOTPART=/dev/mapper/raspberry-btrfs
And creating the /etc/default/raspi-extra-cmdline file, with the
following line:
rootflags=subvol=/bullseye/root/@
-- Solution
The grub-common package has some interesting special handling of Btrfs
(and ZFS) root filesystems in /etc/grub.d/10_linux that can be
interesting to look at as a reference.
Ultimately, they get the filesystem UUID using grub-probe and the
subvolume path using grub-mkrelpath.
We can get the same information using findmnt:
device="$(findmnt --noheadings --first-only --nofsroot --output=source /)"
subvolume="$(findmnt --noheadings --first-only --output=fsroot /)"
uuid="$(findmnt --noheadings --first-only --output=uuid /)"
fstype="$(findmnt --noheadings --first-only --output=fstype /)"
Then it's just a matter of testing when fstype equals btrfs and setting
the cmdline parameters accordingly:
root=UUID=$uuid rootflags=subvol=$subvolume
Note: I tried guarding rootflags against whitespace in $subvolume using
double quotes, but initramfs just blindly wordsplits the cmdline, so it
can't be helped.
ZFS will likely need something similar, but I don't have any experience
with it.
-- Hardware and storage layout tested
I'm using a Raspberry Pi 4 Model B with a Micro SD card and an USB HDD
The examples above are with the following storage configuration:
Micro SD Card
└─ FAT partition (mounted at /boot/firmware)
USB Hard Drive
└─ LVM Volume Group named "raspberry"
└─ LVM Logical Volume named "btrfs" (/dev/mapper/raspberry-btrfs)
└─ Btrfs filesystem
└─ Btrfs subvolume at /bullseye/root/@ (mounted at /)
-- System Information:
Debian Release: bullseye/sid
APT prefers testing
APT policy: (500, 'testing')
Architecture: arm64 (aarch64)
Kernel: Linux 5.10.0-3-arm64 (SMP w/4 CPU threads)
Kernel taint flags: TAINT_CRAP
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE
not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages raspi-firmware depends on:
ii dosfstools 4.2-1
ii dpkg 1.20.7.1
raspi-firmware recommends no packages.
raspi-firmware suggests no packages.
-- Configuration Files:
/etc/default/raspi-firmware changed [not included]
-- no debconf information
Best regards, João Matos
More information about the Pkg-raspi-maintainers
mailing list