Boot Btrfs root partition with Raid1 on Raspberri Pi

This article stems from two different sources:

https://feldspaten.org/2019/07/05/raspbian-and-btrfs/

and

https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=319427

and I decided to summarize the process here, after extensively testing on a Raspberry Pi 4 with 8GB of RAM, and a 64bit OS; I might extend this guide to include setting up a Raid1 with a second disk (spoiler: I already did, down at the end of this page).

WARNING
I suggest testing this procedure on a pendrive where you flashed the image of a raspberry pi os distribution, WITHOUT using apt update & full-upgrade for two reasons:

  1. nothing bad will happen if things go wrong, since it’s not a production environment
  2. you’ll be able to test the kernel update automation AFTER you completed all the steps, by running the apt update && full-upgrade commands

Install requirements and edit needed modules:

sudo apt install initramfs-tools btrfs-tools
# use btrfs-progs if btrfs-tools has "no candidate"
sudo nano /etc/initramfs-tools/modules

Add the following lines to the file and save:

btrfs
xor
zlib_deflate
raid6_pq

Create the initramfs in /boot partition and edit config.txt:

sudo mkinitramfs -o /boot/initramfs-btrfs.gz
sudo nano /boot/config.txt

adding the following line up top and save:

# For more options and informations see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

initramfs initramfs-btrfs.gz

For good measure, check if rebooting the system is succesful. Then sudo poweroff and place the disk (SD, SSD, pendrive) on a linux PC (or just reboot the same Raspberry Pi with a different media you prepared, like an SD card or a pendrive, leaving the disk attached) , and, let’s say the device is recognized as /dev/sdb:

sudo fsck.ext4 /dev/sdb2
sudo btrfs-convert /dev/sdb2                 
sudo mkdir /mnt/rootfs
sudo mount /dev/sdb2 /mnt/rootfs

We’ve just checked if the existing ext4 rootfs is clean, then we converted it to btrfs (it will take quite some time to create the ext2 image to make rollback possible), then created a mountpoint and mounted to it the just converted btrfs root partition.

We now need to update the fstab in this partition so the system will correctly mount at boot:

sudo nano /mnt/rootfs/etc/fstab

Correct the root line (/) by replacing ext4 with btrfs, and make it sure it ends with two 0‘s to disable fsck on it (btrfs has its own builtin filesystem checks, and fsck might return unwarranted errors).

Also, correct /boot/cmdline.txt in the boot partition by replacing, again, ext4 with btrfs, and fsck.repair=yes with fsck.repair=no.

At this point, placing the drive back on the Pi (or removing the other booting media and leaving just the disk) and booting will take you in a btrfs rootfs.

BEWARE navigators: this was my major gripe, as without anything else added to the procedure, a kernel update will be followed by a useless system at the next reboot, because the initramfs won’t be recreated.

User dickon on raspberrypi forums was a great help in the following procedure.

You need to create a script to automatically update initramfs in /boot after a kernel update, so here it is.

sudo nano /etc/kernel/postinst.d/btrfs-update

Insert this code in the script (this will work with a 64bit OS, make sure kernel8.img is the correct filename, you can check against the existing file in /boot, otherwise change accordingly):

#!/bin/bash
if [ "x$2" != "x/boot/kernel8.img" ]; then
	exit 0
fi

echo ============ UPDATE INITRAMFS ==============
mkinitramfs -o /boot/initramfs-btrfs.gz 0,86 EUR
echo ============ UPDATE COMPLETED ==============

then make sure it is executable, and has the same permissions of the other files in the same folder:

sudo chmod 755 /etc/kernel/postinst.d/btrfs-update

At this point, the system will (should) update the relevant initramfs right after each kernel update, freeing you of the hassle of remembering to do it by hand, or risk having a useless system after the next reboot.

It is a good idea to disable swap, since btrfs won’t be able to host a swap file anyway:

sudo systemctl disable dphys-swapfile.service

or alternatively, for a more aggressive approach that will remove the swapfile capabilities entirely:

sudo dphys-swapfile swapoff
sudo dphys-swapfile uninstall
sudo update-rc.d dphys-swapfile remove
sudo apt purge dphys-swapfile

In case you have a spare SSD lying around (who doesn’t) and you want to leverage the advantages of both redundancy and concurrent read speeds, then you can easily use btrfs innate capabilities for this.

You should mirror the partitioning of the system disk on the second SSD (unless there is a large disparity in size), and when that’s done, like detailed here, follow these steps:

sudo btrfs filesystem show

will confirm that the partition assigned to the rootfs mountpoint is the one you just converted a while ago. Let’s assume the partition you want to mirror the rootfs to is /dev/sdb1:

sudo btrfs device add -f /dev/sdb1 /

will assign it to the rootfs mountpoint, which you can confirm by re-issuing:


sudo btrfs filesystem show

that will show the second drive together with the first; you will then instruct btrfs to proceed with the actual mirroring of the data:

sudo btrfs balance start -dconvert=raid1 -mconvert=raid1 /

which might take some time depending on the amount of used space on the partition.

From now on, you will be able to add even more drives, or remove failing ones to substitute them, and there is plenty of resources online that you can search for without me having to detail them all in here.

Leave a Reply

Your email address will not be published. Required fields are marked *