With a recent reinstall of Ubuntu 20.04 on my personal computer, I decided that I wanted to explore a new type of filesystem, and find a replacement for how I used the traditional ext4 and LVM - and I settled on btrfs. While I was and am excited about the power of this next-generation filesystem, I've discovered that it doesn't run itself - with powerful features comes complexity. Over the next few weeks, I plan to write a few posts on what I've learned about btrfs, how to manage and maintain it, and a few things you may not expect if you are used to running Ubuntu with ext4 and LVM.

Background

The computer I am testing on has four disks: one 1TB, one 2TB SSD, and two additional 512GB NVMe SSDs. The 1TB and 2TB disks are managed by a hardware RAID controller.

It's a personal computer used for gaming and daily use, as well as a place I experiment. It runs a small single-node Kubernetes cluster which I use for automated builds of some of my repos, for running Folding@Home, and several other services. You can learn more about this machine and my other infrastructure from the README for my homelab's repository.

During the reinstall, I also chose to dual-boot Windows and Linux, splitting the main disk in two: 200GB for the Ubuntu root (/) and 800GB for Windows. The two 512GB drives don't have a hardware RAID controller, but I wanted to use those in RAID1 for the /home folder in Ubuntu.

$ sudo lsblk
sda           8:0    0   1.8T  0 disk  
└─md126       9:126  0 931.5G  0 raid1 
  ├─md126p1 259:2    0   100M  0 part  /boot/efi
  ├─md126p2 259:3    0    16M  0 part  
  ├─md126p3 259:4    0 735.6G  0 part  <-- Windows 
  ├─md126p4 259:5    0   499M  0 part  
  └─md126p5 259:6    0 195.3G  0 part  /
sdb           8:16   0 931.5G  0 disk  
└─md126       9:126  0 931.5G  0 raid1 
  ├─md126p1 259:2    0   100M  0 part  /boot/efi
  ├─md126p2 259:3    0    16M  0 part  
  ├─md126p3 259:4    0 735.6G  0 part  <-- Windows  
  ├─md126p4 259:5    0   499M  0 part  
  └─md126p5 259:6    0 195.3G  0 part  /
nvme0n1     259:0    0 465.8G  0 disk  /home
nvme1n1     259:1    0 465.8G  0 disk  
lsblk output showing RAID disks and NVME additions disks

I also have spent a significant amount of time in the past testing different systems of backup and restore for this machine, out of curiosity, including Ubuntu's built-in Deja Dup, duplicacy, and full-disk backups with dd and tar, and looked forward to some of the features btrfs provides to make backups easier.

So, with these goals in mind, what are some of the features btrfs provides to make this happen?

btrfs - a next-generation filesystem

btrfs was developed beginning in 2007, and merged into the Linux kernel mainline in 2009, and declared stable in 2013. The name has various pronunciations, and is a reference to the filesystem's core data structure: a copy-on-write (COW) B-tree.

Built-in to btrfs are a number of features you may not expect the filesystem to provide for you. Commonly-desired features that Linux users would install additional software for have been built into the filesystem from the beginning.

Device management

btrfs provides users some ways to manage physical devices directly, like LVM, as well as providing some support for software-RAID arrangements, like mdadm. Though not meant to compete feature-for-feature, btrfs supports:

  • Creating a filesystem with metadata, data, or both in RAID 0, RAID 1, RAID 10, RAID 5 and RAID 6
  • Performing day-2 addition of disks to an existing filesystem, and conversion between RAID levels
  • Resizing the filesystem to take advantage added disks, or decrease the size of the filesystem to account for lost disks
  • Balancing data across disks, including when replacing disks due to failure

btrfs doesn't provide complex volume group and logical device management like LVM - instead, all devices are joined into a common pool, and individual pieces of data are arranged onto the storage pool according to RAID configuration.

However, though devices are pooled within each btrfs filesystem, it is possible to have multiple filesystems active, and the command btrfs device scan searches all devices for distinct btrfs filesystems.

The Ubuntu installer creates one btrfs filesystem for the root directory. I placed this on a 200GB partition of the hardware RAID controlled pair of disks. I moved the home directory to a second filesystem using btrfs' RAID:

sudo mkfs.btrfs -m raid1 -d raid1 /dev/nvme0n1 /dev/nvme1n1
sudo mount /dev/nvme0n1 /home
Creating a second btrfs filesystetm with software RAID1 for /home
$ sudo btrfs filesystem show
Label: none  uuid: 3451815e-07c2-4b60-bd43-68fd338aa881
        Total devices 1 FS bytes used 172.82GiB
        devid    1 size 195.31GiB used 177.03GiB path /dev/md126p5

Label: none  uuid: af5e3ee6-40c6-4dc0-82f3-5f6a025f842c
        Total devices 2 FS bytes used 49.55GiB
        devid    1 size 465.76GiB used 83.03GiB path /dev/nvme0n1
        devid    2 size 465.76GiB used 83.03GiB path /dev/nvme1n1

Subvolumes

btrfs allows users to create multiple subvolumes within a filesystem. btrfs subvolumes resemble as folders within the filesystem, and can be nested within each other. The mounted filesystem within which you create the subvolume is the subvolume's parent. Mounting a parent subvolume implicitly mounts the child subvolumes at their path. Each subvolume has a UUID, a unique ID, and is also uniquely identified by its name, which is also the path at which it will appear under its parent. Because this name is also the subvolume's path, moving a subvolume is the same as renaming it.

However, subvolumes differ from folders in a number of ways:

  • Subvolumes can be individually mounted at another location
  • Subvolumes are globally queryable with btrfs subvolume list <path>

All btrfs filesystems have at least one subvolume: this is the root subvolume, and by convention has ID=5 and the hidden name FS_TREE. This root subvolume is not included in btrfs subvolume list, but in filesystems with additional subvolumes, it will be the ultimate parent of any child subvolumes. The top level field of btrfs subvolume list indicates the ID of the parent subvolume. With -a, the path field shows the name of the parent as the first part of the path.

$ sudo btrfs subvolume list -atq /
ID      gen     top level       parent_uuid     path
--      ---     ---------       -----------     ----
256     336674  5               -               <FS_TREE>/@
Ubuntu subvolumes for the root filesystem on OS install

Any subvolume within the filesystem can be mounted as the root, not just FS_TREE. Ubuntu, in fact, creates a child subvolume with the name @ and mounts this subvolume to the path / instead of mounting FS_TREE to that location.

For more help understanding subvolumes and when to use them, check out the btrfs SysadminGuide.

Snapshots

Because btrfs is copy-on-write, it supports lightweight snapshots which capture the current state and only record the changes made to the filesystem since the previous snapshot.

These snapshots are actually new subvolumes, identical to plain subvolumes except that they are populated with the content of their source at creation. This is done without consuming any space initially because the new subvolume simply references the data without making a new copy. Snapshots live within the filesystem as subvolumes, and are mountable and browseable like others.

Read-only snapshots can maintain the state of the filesystem at a fixed point in time, while read-write snapshots can restore such a snapshot and be used to recover.

Compression

On top of these features, btrfs also supports automatic compression using one of several algorithms: zlib, lzo, and zstd. Compression can be activated at mount-time, either using a btrfs-designed heuristic for when files are compressive by specifying -o compress (though some users do not recommend this approach), or on all files by specifying -o compress-force. You can also use extended attributes to enable or disable compression on individual files using the command btrfs property set <file> compression ... or chattr +c.

Next post

While btrfs has some amazing features, it can make familiar tools behave in unexpected ways - including old standbys like du and df! In the next part, I'll walk through some of the best tools to interact with btrfs and maintain it in the long-term.


Credit for the title image to CyHawk - Own work based on [1]., CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=11701365