Featured image of post Raspbian and btrfs

Raspbian and btrfs

I’ve just got a brand new Raspberry Pi 4. For now I’m just playing around a bit with it. Until openSUSE Leap will be available, I’m using Raspbian Buster which comes by default with ext4. Since I want to have snapshots, the first thing I want to do is to convert the existing root partition into btrfs. So let’s do this.

0. Get Raspbian

First, flash Raspbian to a SD card and boot it. I also recommend to run a system update after booting into Raspbian. There are plenty of tutorials on the internet, that are probably far better than what I can write.

1. Prepare initramfs

In Raspbian btrfs is included as module. In order to make the kernel mount a btrfs root filesystem, we need to build the corresponding initramfs. First install the necessary tools

sudo apt install initramfs-tools btrfs-tools

Now we add the btrfs module to /etc/initramfs-tools/modules

$ vi /etc/initramfs-tools/modules
btrfs
xor
zlib_deflate
raid6_pq

Next is to build the initramfs

mkinitramfs -o /boot/initramfs-btrfs.gz

And tell the bootloader to load the initramfs, by editing /boot/config.txt

$ vi /boot/config.txt
# 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

[...]

And then reboot the device, to check if everything is set up properly.
If the boot succeeds, shutdown the Raspberry and take the SD-Card to another computer. If you run at this stage into trouble, probably a filename is wrong and you should be still able to recover. Otherwise: Just start from scratch - at this point really nothing is lost.

2. Convert ext4 rootfs to btrfs

In my case I insert the SD card into my laptop. The SD card gets recognised as /dev/mmcblk0 and contains the following partitions:

$ fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 7.48 GiB, 8017412096 bytes, 15659008 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x4301c17b

Device         Boot  Start      End  Sectors  Size Id Type
/dev/mmcblk0p1        8192   532480   524289  256M  c W95 FAT32 (LBA)
/dev/mmcblk0p2      540672 15659007 15118336  7.2G 83 Linux</code></pre>

To convert the filesystem to btrfs, we are now doing the following steps:

  1. Optional: Make sure, the rootfs is clean (fsck)
  2. Convert ext4 to btrfs using btrfs-convert
  3. Mount new btrfs root
  4. Edit /etc/fstab
  5. Edit /boot/cmdline.txt

On my system, I have to do the following steps

$ fsck.ext4 /dev/mmcblk0p2                     # Optional but I recommend it
$ btrfs-convert /dev/mmcblk0p2                 # Convert ext4 root to btrfs
$ mkdir /mnt/sdcard                            # Here we will mount the rootfs
$ mount -t btrfs /dev/mmcblk0p2 /mnt/sdcard    # Mount newly created rootfs

Now we edit /etc/fstab and change ext4 to btrfs. We also need to disable the filesystem-check by setting the last two digits in the btrfs line to 0s

$ vi /mnt/sdcard/etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=4301c17b-01  /boot           vfat    defaults          0       2
PARTUUID=4301c17b-02  /               btrfs   defaults,noatime  0       0

Lastly we edit /boot/cmdline.txt from the SD-Card. We need to replace rootfstype=ext4 to rootfstype=btrfs and set fsck.repair=no

# vi /mnt/sdcard/boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=a0683fcf-02 rootfstype=btrfs elevator=deadline fsck.repair=no rootwait

3. Now the fun starts

This is only the kickoff. Now the funny things, like subvolumes, snapshots ecc. start

Have a lot of fun! :-)

Caveats

  • After a kernel update, you will need to run mkinitramfs again. Probably it’s the best to only do manual kernel updates (even as security updates) as otherwise your Raspi will not boot again.

Additional notes

Check those notes, in case something went wrong. Those emphasis the steps I had to to to make this work

  • Fsck had cause me a lot of trouble. In case you run into mount invalid errors, check if you have disable fsck in /etc/fstab (the last zero) and in /boot/cmdline.txt
  • Apparently btrfs-convert doesn’t change the UUID. If you find yourself with “device not found” or similar errors, this might has changed and you will need to change the UUIDs
  • After a kernel update you will need to run mkinitramfs again. Keep that in mind (and perhaps disable auto-updates)

Pitfalls

mounting /dev/mmcblk0p2 failed: Invalid argument

Crappy image of the console output with the “mounting … failed: invalid argument” error

I got this error message when I forgot to edit cmdline.txt. Make sure, you have configured /boot/cmdline.txt correctly (double-check rootfstype=btrfs and fsck.repair=no):

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=a0683fcf-02 rootfstype=btrfs elevator=deadline fsck.repair=no rootwait

Update 2021-01-06

Updated a typo, it was vi /boot/cmdline.txt should have been vi /mnt/sdcard/boot/cmdline.txt. Thanks Frank!