Linux: build in BTRFS in the configs for Raspberry Pi 2 and 3

Created on 11 Dec 2016  路  13Comments  路  Source: raspberrypi/linux

We have a ~5k deployment of Raspberry Pi 2 and Raspberry Pi 3 on Raspbain with btrfs roots. They are 20x less prone to MicroSD card corruption issues than ext partitions in our experiment. We had 9 failures over 3 months vs ~1% a month with ext. The only issue is that btrfs get bonked by the standard kernels. We currently maintain separate kernels just for this small issue. While I think Raspbian should just move over to BTRFS to save everybody the hassle, a meaningful step would just to bake BTRFS in the default configs for BCM2836 and BCM2837.

Most helpful comment

@dsx724 You don't need to do that. There is no need to include it in the kernel as it's already built as a module and initrd/initramfs support was added back in 2013 ( https://github.com/raspberrypi/linux/issues/392 ).
All you have to do, is build an initramfs with btrfs module included.

You can do that using initramfs-tools.
First you add btrfs to /etc/initramfs-tools/modules and build it.
For RPi1 and 4.4.38 its something like: mkinitramfs 4.4.38+ -o initramfs.img
while for RPi2/3 its mkinitramfs 4.4.38-v7+ -o initramfs7.img
You copy these files to /boot and edit your config.txt to include at the beginning:
[pi1]
initramfs initramfs.img followkernel
kernel=kernel.img
[pi2]
initramfs initramfs7.img followkernel
kernel=kernel7.img
[all]
the rest goes here

I also think there is a [pi3] filter, but cannot confirm. If you don't have any RPi1 you can skip the filters and only add the lines applicable to pi2/3.

You also need to edit the cmdline.txt: rootfstype=btrfs
and if you are using btrfs subvolumes add: rootflags=subvol=yoursubvolname

All 13 comments

While I personally would love to see this (within reason), there's a couple of things to think about here:

  1. BTRFS is _HUGE_ compared to most other filesystems. I'd expect building it in to increase the kernel memory footprint by 100kB+.
  2. Raspbian uses (and requires) an initrd, because of this, BTRFS does not need to be built-in to be used as a root filesystem.
  3. BTRFS development is moving fast. Far faster than the Raspberry Pi kernel (4.9 just got released upstream, and Raspbian, NOOBS, and most other things are still shipping 4.4). Unless that changes, I wouldn't in good conscience suggest that BTRFS become the default.
  4. BTRFS shouldn't be any less susceptible to SD card corruption than any other filesystem, it is just more likely to recover safely from it. To be able to actually do so reliably though, it would need to be either DUP profile for both data and metadata, or two partitions on the card with RAID1 profile for both data and metadata. The first case isn't reliably supported on older kernels, and the second severely hurts performance.
  5. BTRFS in general is significantly slower than than ext4. I doubt most people are going to be willing to take the performance hit on an already slow storage device.
  1. Raspbian uses (and requires) an initrd, because of this, BTRFS does not need to be built-in to be used as a root filesystem.

Raspbian neither uses nor requires an initrd. You can configure the kernel to use one, but it isn't a tested configuration.

Really? I was under the impression that current versions of Raspbian were using SystemD, which functionally requires an initrd.

I wouldn't exactly say that's an untested configuration either, as I'm pretty certain that at least the Pi ports of Fedora and Ubuntu use one.

Systemd supports operation with and without an initrd, and Raspbian uses it without. By "untested configuration" I meant that Raspberry Pi don't test it. I could have written "unsupported configuration", but that would have suggested that you'll get no help from us if it doesn't work, which isn't the case.

@dsx724 You don't need to do that. There is no need to include it in the kernel as it's already built as a module and initrd/initramfs support was added back in 2013 ( https://github.com/raspberrypi/linux/issues/392 ).
All you have to do, is build an initramfs with btrfs module included.

You can do that using initramfs-tools.
First you add btrfs to /etc/initramfs-tools/modules and build it.
For RPi1 and 4.4.38 its something like: mkinitramfs 4.4.38+ -o initramfs.img
while for RPi2/3 its mkinitramfs 4.4.38-v7+ -o initramfs7.img
You copy these files to /boot and edit your config.txt to include at the beginning:
[pi1]
initramfs initramfs.img followkernel
kernel=kernel.img
[pi2]
initramfs initramfs7.img followkernel
kernel=kernel7.img
[all]
the rest goes here

I also think there is a [pi3] filter, but cannot confirm. If you don't have any RPi1 you can skip the filters and only add the lines applicable to pi2/3.

You also need to edit the cmdline.txt: rootfstype=btrfs
and if you are using btrfs subvolumes add: rootflags=subvol=yoursubvolname

@dsx724 can this be closed?

@evilpower Just a quick question if using subvolumes as root. Where do you mount the main btrfs_pool. I was thinking that a mount point inside /boot might be a good place.

@akc42 Depends on personal preference really. Most people I know use a subdirectory of /mnt or a dedicated directory in / for it, and then make a point to only mount it when they actually need it. You might look at how openSUSE or Ubuntu have things set up, their default BTRFS layout mounts it somewhere (because the standard install includes automatic snapshot management), and I would guess that since they are the only two distros really doing this that they're by default the standard to compare against.

Using the instructions here I have created a BTRFS image and successfully been using it for about a month. HOWEVER, I have just come across a nasty problem which I haven't got to the bottom of yet. If the kernel gets upgraded, the system becomes unbootable. Its a bit difficult to track as by then I am only using ssh to connect to my pi, but if I put a monitor and keyboard on, I can see its getting stuck inside the boot prompt with initramfs> showing saying there is no /sbin/init

If there are any ideas of why that is happening and how to overcome it I would be grateful. In the meantime I am going to have to dig around to understand the problem better.

@akc42, I suspect you end up having an initramfs with modules for the old kernel, rather than the one you are running. You'd need to add hooks to update your initramfs when the kernel is updated.

@XECDesign I am coming to the same conclusion.

I've just restored my SD card from a backup and done another upgrade (but not yet rebooted). I thought maybe cmdline.txt had been overwritten - but no. BUT, the filesystem date for initramfs7.img is old compared to kernel7.img

so I rebuilt initramfs7 manually in /boot mkinitramfs 4.4.50+ -o initramfs.img and rebooted and it worked.

How you you add the hooks?

I found this
https://github.com/raspberrypi/firmware/issues/608
which has several ideas about how to create the hooks.

Closing this issue as questions answered/issue resolved.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ensarkarabudak picture ensarkarabudak  路  7Comments

Nuntis-Spayz picture Nuntis-Spayz  路  5Comments

wudo94 picture wudo94  路  5Comments

XECDesign picture XECDesign  路  6Comments

thomasklingbeil picture thomasklingbeil  路  4Comments