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

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

Next is to build the initramfs

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

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:

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

  1. Optional: Make sure, the rootfs is clean (run fstck)
  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

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 0

IMPORTANT: Set the last two settings in /etc/fstab to 0 and 0. The last 0 is especially important for btrfs root, since fsck and btrfs do not go so well together.

Lastly we edit /boot/cmdline.txt. We neet to replace rootfstype=ext4 to rootfstype=btrfs and set fsck.repair=no

IMPORTANT: It is crucial to set fsck.repair=no. I was stuck at some weird "mounting failed: Invalid argument" errors, because the system wanted to perform a fsck and failed.

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 security updates) as otherwise your Raspi might not be able to 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
  • Apperently 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 maybe disable auto-updates)

Common pitfalls

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 (especially the rootfstype=btrfs and fsck.repair=no)

4 thoughts on “Raspbian and btrfs”

  1. I was trying this out but it appears that btrfs-convert has gone missing. What package and version did you use to get btrfs-convert?

    1. I usually rsync whole filesystems with this command line:

      sudo rsync -a --progress -AHXDE --checksum --sparse --exclude=/dev/* --exclude=/run/* --exclude=/home/*/.gvfs --exclude=/home/*/.mozilla/firefox/*/Cache --exclude=/home/*/.cache/chromium --exclude=/home/*/.thumbnails --exclude=/media/* --exclude=/mnt/* --exclude=/proc/* --exclude=/sys/* --exclude=/tmp/* --exclude=/home/*/.local/share/Trash --exclude=/var/run/* --exclude=/var/lock/* --exclude=/lib/modules/*/volatile/.mounted --exclude=/var/cache/apt/archives/* /mnt/old-ext4-partition/ /mnt/new-btrfs-partition/

      The only caveat is that one has to remember to recreate all the mountpoints in /mnt on the target filesystem.

      Another improvement to the article would be to mount the root filesystem with compression enabled:

      Instead of:

      PARTUUID=4301c17b-02 / btrfs defaults,noatime 0 0

      better mount settings would be:

      PARTUUID=4301c17b-02 / btrfs defaults,compress=zlib 0 0

      Great article anyway!

      1. Thanks for the reply! I'm glad someone actually finds this useful 😉
        I did this once and use now the Raspberry for Kodi, so it's not in production anymore. Tinkering is a process that never stops.

        The idea with compression is definitely worthwhile trying out. I had enough issues to think about while setting this up, but that might be really useful for some applications. Good idea.

        Thanks for the input!

  2. Using "fstransform" for the conversion from ext4 to btrfs worked for me as replacement of the missing "btrfs-convert". As btrfs is not officially supported though, you need to use the "--force-untested-file-systems" command line switch.

    Concerning the kernel update issue, it is possible to write kernel update hooks so that a new initramfs image is generated and config.txt is updated after a new kernel update:
    https://github.com/raspberrypi/firmware/issues/608#issuecomment-224260711

Leave a Reply

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