Btrfs on Librem 5 eMMC

Image: Screenshot from Librem 5 running from a NexDock. Open windows are Gnome Disks, neofetch, vim /etc/fstab, and mount | grep btrfs.

So, I am prone to breaking things and wanted another option to rollback to a working filesystem in addition to reflashing and Jumpdrive. btrfs allows easy creation and manipulation of snapshots of the root filesystem and adds some nice features like transparent file compression and SSD awareness and optimizations.

It was a valuable journey figuring things out as initially I thought I would have to wrestle with initramfs–which I’ve never had to manipulate before this point–but it turned out not needing much manipulation. btrfs does have some overhead compared to ext4, especially if you’re using compression as you are trading some CPU processing for reduced disk use and potentially reduced writes in the future, but I foresee having snapshots alone will save me some headaches.

What you need

  • uuu
  • Jumpdrive
  • A running system with btrfs-progs that support --uuid copy in btrfs-convert (I used an Ubuntu 22.04 Live USB)

General steps

  1. Back up your device.

  2. Install btrfs-progs on the Librem 5: sudo apt install btrfs-progs.

  3. Add btrfs to /etc/initramfs-tools/modules.

  4. Update the initial RAM disk: sudo update-initramfs -u.

  5. Restart the phone, load Jumpdrive, and plug into system with btrfs-progs available and a terminal open.

  6. (If your eMMC is the LUKS variant) Unlock the root partition: sudo cryptsetup luksOpen /dev/$LIBREM5_PARTITION librem5.

  7. Check the root partition for errors: sudo e2fsck -fvy /dev/mapper/librem5. (Use /dev/$LIBREM5_PARTITION if you’re not running the LUKS variant)

  8. Convert the root partition: sudo btrfs-convert --uuid copy /dev/mapper/librem5. (Use /dev/$LIBREM5_PARTITION if you’re not running the LUKS variant)

  9. Mount the root partition. I mounted it to /mnt/librem5.

  10. Create a root subvolume using sudo btrfs subvolume create /mnt/librem5/$NAME (I named the root subvolume @) and mv everything from the root of the partition into it.

  11. Find the subvolid of @ (sudo btrfs subvolume list -p /mnt/librem5/) and set @ to be the default mount: sudo btrfs subvolume set-default $SUBVOLID /mnt/librem5/.

  12. (Optional) Create other subvolumes based on your needs. For example, I additionally made @home for /home and @logs for /var/log. As these will be mounted to their respective directories, make sure to move any files into those subvolumes after creation.

  13. Delete the original filesystem data: sudo btrfs subvolume delete /mnt/librem5/ext2_saved.

  14. (Optional) Enable zstd compression for @ and other subvolumes, as desired, and compress existing files:

sudo chattr +c /mnt/librem5/@ &&
sudo btrfs property set /mnt/librem5/@ compression zstd &&
sudo btrfs filesystem defragment -r -v -czstd /mnt/librem5/@
  1. Make the file data more contiguous: sudo btrfs filesystem defrag -v -r -f -t 32M /mnt/librem5/.

  2. Re-balance the filesystem: sudo btrfs balance start /mnt/librem5/

  3. Edit /etc/fstab to properly mount your subvolumes. Note that $UUID will be the same as what’s already in there for your root partition since we used --uuid copy during conversion. It should look something like this:

proc /proc proc defaults 0 0
UUID=$UUID / btrfs subvol=@ 0 0
UUID=$UUID /home btrfs subvol=@home 0 0
UUID=$UUID /var/log btrfs subvol=@logs 0 0
UUID=... /boot ext2 errors=remount-ro 0 2
  1. Clean up and unmount the partitions. Closing LUKS is only needed if you’re using the LUKS variant:
sudo sync &&
sudo umount /mnt/librem5 &&
sudo cryptsetup luksClose librem5

Not 100% sure update-initramfs depends on /etc/fstab being correct

When I did this originally, I did step 17 after step 3 because I don’t know how initramfs actually works. But after examining the contents of the initial RAM disk using unmkinitramfs and seeing no reference to the new fstab and no need to change any UUIDs since we didn’t change any, I think the order that I’ve written this works.

You are welcome to do what I did and edit fstab before updating the initial RAM disk!

16 Likes

Nice. I want the next version of the L5 to have 8 eMMC units so I can setup a mirrored zfs file system with 2 for failover.

>_<

1 Like

I think it might take some time before an 8-eMMC Librem 5 will be made. Not sure why, but it may be a minute. :3c

(In theory, you could replace the modem and Wi-Fi modules with SSDs, add an SD card, and use btrfs volume management to have your filesystem working similar to RAID{0,1,10,5,6} right now, though. And I don’t believe there’s technically anything stopping someone from compiling OpenZFS on their Librem 5 and using it, either, but I’ve never touched OpenZFS beyond reading about it.)

2 Likes

Nope, but you could replace the WiFi card with an SD card, and the modem with a USB drive.

1 Like

WiFi card could be replaced with a USB drive too.

Nice. Copy on write file systems will make the flash memory last longer. Also, there is another thread speculating that backing up the SMS messages database while the application has it open may corrupt the backup. With btrfs, the startup or shutdown process could create a snapshot for the entire file system (when files not being modified), and when the phone starts up again, the differences in the snapshot from the last transmitted snapshot (that contains the SMS database in a properly shutdown state) can be sent off device while the phone is operating normally.

2 Likes

Man, I totally forgot about btrfs-send and btrfs-receive and being able to send snapshots to somewhere else, even through ssh. Unintended benefit!

2 Likes

That is the backup system that I would implement. The destination would let us download files to restore if we only need a few files fixed. A Jumpdrive would be able to restore the entire device. Of course, I would only run it on my home network where I have the bandwidth and privacy. I did a simple search to see if an open source NAS supported receiving btrfs. I found https://github.com/digint/btrbk I would assume that more tinkering is required to make it user friendly.

I like that this also adds the compression option. 32GB is kind of small, and compression makes better use of that, especially the programs and libraries that root file systems often contain.

I remember the commands to send-receive snapshots to not be that difficult and simple enough to write a few-line script and add to cron or run interactively whenever you wanted to send an incremental snapshot somewhere. I’ve never done it through a network though and, high level, I assume is it’s a matter of “How do we let the receiving system know we want to send a snapshot so it’s ready for it?”

As for the compression, the disk usage numbers on my Librem 5 are pretty significant in actual disk usage versus its uncompressed size:

# sudo mount /dev/mapper/crypt_root -o subvol=/ /mnt
# sudo compsize /mnt/
Processed 258597 files, 133779 regular extents (189001 refs), 136928 inline.
Type       Perc     Disk Usage   Uncompressed Referenced  
TOTAL       58%      4.9G         8.4G          12G       
none       100%      2.9G         2.9G         4.3G       
zlib        26%      2.9M          10M          10M       
zstd        36%      1.9G         5.4G         7.9G       
prealloc   100%       42M          42M          30M

I’m using zstd with the standard compression level (I believe that’s 3).

2 Likes

Nice. One nice thing about a small main storage device, is that it is not difficult to find 32GB of storage on a spare Linux device, so going all out with a NAS is not necessary. I also remember that zstd is relatively easy on the CPU for the compression that you get. For slower storage mediums, like USB 2.0 flash drives or SD cards, it can even speed things up.

One more feature that snapshots add: An option to rollback a bad update. This is one of the reasons why I have a test phone. If you have not customized your phone much, updates should be less of an adventure, but I worry that the more customizations to the OS that we do, the more likely something is to break on an update. People who want to experiment with WayDroid updates might appreciate this too. I expect that WayDroid images will compress well too.

4 Likes

I hope we will get BTRFS out of the box at some point in the future.

3 Likes

Fedora automatically installs btrfs for workstation installs. For the Librem 5 and the Librem laptops, we would probably have to wait until Debian changes their default file system to btrfs, unless PureOS diverges from Debian more. For a while, I expect that Purism has more important things to do. The next version of Debian that is coming out soon will remain on ext4, and I do not know if there is a discussion on changing it for the version after that.

Debian 12 is scheduled to be released on June 10. After that, PureOS can switch to that too. I expect that there will be some delay. I am not sure if it will affect anything on this topic functionality wise (improved btrfs performance is a feature of Debian 12), but after having a fresh major version on my phone, I will play with some more changes. That way, I do not have to do it twice or risk doing something to the upgrade path. Definitely make sure that you have Jumpdrive working for when you need to recover the operating system if you want to play with changing the root file system or editing the fstab file. Thank you sentamalin for the steps above.

1 Like

It’ll probably be easier to choose which filesystems to install on our respective devices once an actual installer exists for the phone versus just flashing a new image. I recognize that flashing phones is currently in-vogue even with Android-based projects so this might face some inertia, but it could happen at a future point with PureOS.

Mobian already has an installer where you can choose a filesystem for an eMMC install and if you want to set up LUKS, though the installer is still in alpha and only for the PinePhone and PineTab.

1 Like