Btrfs/Getting Started

From Forza's ramblings

Getting Started with Btrfs[edit | edit source]

A disassembled Hard Disk.

Hi there,

If you are new to Btrfs this guide will help you set up a basic Btrfs filesystem. You can also read up on the more advanced topics such as snapshots, backups, compression and volume management.

Before continuing you may want to read a summary of the many unique Btrfs features.

Preparing your disks[edit | edit source]

Although Btrfs allows the use of raw disks, it is recommended that you create a partition table and at least one partition for Btrfs. Without the partition table, other tools and operating systems might not handle the disk correctly, causing data loss.

I recommend you use a GUID Partition Table (GPT) instead of the legacy MBR/DOS type. GNU Parted is available on most systems, but cfdisk, fdisk and other tools can do the job just as well.

Single, multi-disk and RAID[edit | edit source]

Btrfs can be used on single disks as well using different profiles (RAID) on multiple disks. See the Volume management chapter for a full list of supported profiles.

Btrfs supports combining disks of different sizes, even with RAID profiles. Use the excellent disk space calculator at https://carfax.org.uk/btrfs-usage/ to see how you best can combine your disks.

Screenshot of the disk space calculator.
Disk space calculator showing 3 devices in a RAID-1 configuration

There is also a command line tool from the python-btrfs package.

# btrfs-space-calculator -m raid1 -d raid1 4TiB 6TiB 8TiB
Target metadata profile: RAID1
Target data profile: RAID1
Mixed block groups: False
Total raw filesystem size: 17.58TiB
Device sizes:
  Device 1: 3.91TiB
  Device 2: 5.86TiB
  Device 3: 7.81TiB
Metadata to data ratio: 1:200
Estimated virtual space to use for metadata: 45.00GiB
Estimated virtual space to use for data: 8.75TiB
Total unallocatable raw amount: 0.00B
Unallocatable raw bytes per device:
  Device 1: 0.00B
  Device 2: 0.00B
  Device 3: 0.00B

SSD and NVME disks[edit | edit source]

If you have an NVME or SSD disk, it is good practice to empty it using blkdiscard. Discards tells the drive's firmware that the disk is empty and it improves it's performance and wear. Do this before you create any partition tables as it will erase everything of the disk.

Partitioning[edit | edit source]

First, setup a partition table on your disks using GNU Parted. Make sure you start the partion on the 4MiB boundary to ensure alignment with the disk's block size.

Partition Filesystem Start End Partition type
/dev/sdb1 Btrfs 4MiB 100% Linux filesystem
/dev/sdc1 Btrfs 4MiB 100% Linux filesystem

Invoke parted with the disk you want to edit:

# parted /dev/sdb
 GNU Parted 3.2
 Using /dev/sdb
 Welcome to GNU Parted! Type 'help' to view a list of commands.
 (parted) unit MiB    # This changes the displayed unit to MiB (Megabytes)

First check there is no existing partitions or partition tables on the disk:

(parted) print
 Error: /dev/sdb: unrecognised disk label
 Model: ATA VBOX HARDDISK (scsi)
 Disk /dev/sdb: 102400MiB
 Sector size (logical/physical): 512B/512B
 Partition Table: unknown
 Disk Flags:

Create a GPT partition table:

(parted) mklabel gpt

Create a partition:

(parted) mkpart my-btrfs btrfs 4MiB 100%

You can list the resulting layout using print command:

(parted) print
 Model: ATA VBOX HARDDISK (scsi)
 Disk /dev/sdb: 51200MiB
 Sector size (logical/physical): 512B/512B
 Partition Table: gpt
 Disk Flags:
 
 Number  Start    End       Size      File system  Name      Flags
  1      4.00MiB  51299MiB  51295MiB  btrfs        my-btrfs

You should make sure you have a partition on every disk you want to add to your Btrfs filesystem.

Formatting aka mkfs.btrfs[edit | edit source]

The basic formatting command is

# mkfs.btrfs -L <label> --data <profile> <device_1> <device_2> <device_n>

Btrfs support several different RAID profiles. Read more about profiles and Volume management on the Btrfs/Features page.

This will create a standard btrfs filesystem spanning both disks and give it the name my-data. The filesystem will have the size of the sum of both disks, in this case 150GiB.

# mkfs.btrfs -L my-data --data single /dev/sdb1 /dev/sdc1
btrfs-progs v4.19.1
See http://btrfs.wiki.kernel.org for more information.

Label:              my-data
UUID:               a36f20ff-f0b1-466d-a7dc-355c189b3e39
Node size:          16384
Sector size:        4096
Filesystem size:    149.99GiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         RAID1             1.00GiB
  System:           RAID1             8.00MiB
SSD detected:       yes
Incompat features:  extref, skinny-metadata
Number of devices:  2
Devices:
   ID        SIZE  PATH
    1    50.00GiB  /dev/sdb1
    2   100.00GiB  /dev/sdc1

If you rather want to use RAID1 (mirroring) you would do:

# mkfs.btrfs -L my-data --data RAID1 /dev/sdb1 /dev/sdc1

Btrfs as root filesystem[edit | edit source]

A common way to set up a single disk root filesystem is to use a separate boot, swap and root partitions. Although Btrfs supports swap files in recent kernels, there are still some caveats. It is better to use a swap partition when possible.

Follow the guide in the Partitioning section to prepare your partitions.

Partition Filesystem Start End Partition type
/dev/sda(none) (bootloader) 0 4MiB BIOS boot
/dev/sda1 Btrfs/FAT32* 4MiB 1GiB Boot or EFI system partition (ESP)
/dev/sda2 Swap 1GiB 4GiB Swap partition
/dev/sda3 Btrfs 4GiB 100% Linux filesystem
1) Note that if you use UEFI boot instead of Bios boot, you need a FAT32 formatted EFI System Partition.
2) Old versions of the GRUB boot loader may not support Btrfs for /boot (/dev/sda1). In that case use ext4 or FAT32

There is a very good guide in the Gentoo handbook on how to choose and determine your partition layout.

When deciding on swap space you should estimate the needed size based on RAM and if you are going to use Hibernation. There is a good guide over at the Ubuntu Community pages that explains why you need swap and how much to use.

 RAM   No hibernation    With Hibernation  Maximum
 1GB              1GB                 2GB      2GB
 2GB              1GB                 3GB      4GB
 3GB              2GB                 5GB      6GB
 4GB              2GB                 6GB      8GB
 5GB              2GB                 7GB     10GB
 6GB              2GB                 8GB     12GB
 8GB              3GB                11GB     16GB
12GB              3GB                15GB     24GB
16GB              4GB                20GB     32GB
24GB              5GB                29GB     48GB
32GB              6GB                38GB     64GB
64GB              8GB                72GB    128GB

Subvolumes[edit | edit source]

Btrfs subvolumes is one of the unique features of Btrfs. A subvolume is a part of the filesystem but has its own independent file/directory hierarchy.

Subvolumes is a great way to separate your data in logical sections. They share all the space for the filesystem, but can be mounted separately, be snapshotted and sent for backups. In most ways, a subvolume looks like a normal directory. You can copy it, write in it, rename it, etc. Subvolumes can also be nested.

When you mkfs.btrfs btrfs automatically creates a default (toplevel) subvolume. This will be the default subvolume when mounting the filesystem without subvol or subvolid options.

I usually make two directories, volume and snapshot in which I create all subvolumes. This makes it easy to separate snapshots from normal subvolumes. Try not to create nested subvolumes as it makes things more complicated to manage.

toplevel            (default subvolume root directory)
+-- dir_1           (normal directory)
|   +-- file_2      (normal file)
|   \-- file_3      (normal file)
\-- volume          (directory)
    +-- root        (subvolume)
    |   \-- file_4  (normal file)
    +-- home        (subvolume)
    +-- tmp         (subvolume)
    \-- file_5      (normal file)
\-- snapshot        (directory)

Use the -o subvol= mount option to specify the subvolume to mount.

# mount /dev/sdb1 /home    -o subvol=volume/home # mounts the home subvolume in /home
# mount /dev/sdb1 /var/tmp -o subvol=volume/tmp  # mounts the tmp  subvolume in /var/tmp

Many distributions have lots of subvolumes predefined. It's usually not necessary and is often a legacy from older times when we were used to having separate partitions. With Btrfs you can add and remove subvolumes at any time. If unsure, start with a few subvolumes, and expand later if you need to.

Example of a mounted root filesystem layout:

Path Description
/ The root subvolume
/home This where users' home directories are

/etc/fstab: It is usually best to use UUID= instead of /dev/sda in fstab. The command blkid gives you a list of devices and filesystems's UUID.

# blkid
/dev/sda2: LABEL="btrfs-boot" UUID="1128e72e-b00f-4c2a-a1e1-afa89f3c11cc" UUID_SUB="43e7d65d-835a-40d5-a204-c84882532db5" BLOCK_SIZE="4096" TYPE="btrfs" PARTUUID="817e8dfa-28bb-40cc-9289-da9f77ad6c91"
/dev/sda3: LABEL="btrfs-root" UUID="446d32cb-a6da-45f0-9246-1483ad3420e0" UUID_SUB="a286a010-6db4-4f79-aa2c-a3b449b40e67" BLOCK_SIZE="4096" TYPE="btrfs" PARTLABEL="btrfs-root" PARTUUID="7e2b7b21-625c-4908-8b0e-b827254000e5"
/dev/sda4: LABEL="swap"       UUID="a386e543-8698-4422-8a57-53ea545b356e" TYPE="swap" PARTLABEL="swap" PARTUUID="fb3fd442-1654-4587-8580-fd3644c3f9f3"
# /etc/fstab
UUID=a386e543-8698-4422-8a57-53ea545b356e   none          swap    sw,pri=0                                        0 0
UUID=446d32cb-a6da-45f0-9246-1483ad3420e0   /             btrfs   noatime,space_cache=v2,subvol=volume/root       0 0
UUID=446d32cb-a6da-45f0-9246-1483ad3420e0   /home         btrfs   noatime,space_cache=v2,subvol=volume/home       0 0
UUID=446d32cb-a6da-45f0-9246-1483ad3420e0   /var/tmp      btrfs   noatime,space_cache=v2,subvol=volume/var_tmp    0 0
UUID=446d32cb-a6da-45f0-9246-1483ad3420e0   /mnt/rootvol  btrfs   noatime,space_cache=v2,subvol=/                 0 0

Take a note of the last line. This is your top-level subvolume. In here you can access all subvolumes, snapshot them, and do maintenance tasks.

# ls -l /mnt/rootvol/
drwxr-xr-x 1 root root 6224 Aug  2 13:01 snapshots/
drwxr-xr-x 1 root root  190 Apr 30 22:28 volume/
# ls -l /mnt/rootvol/volume
drwxr-xr-x 1 root   root     36 Jul 30 22:27 home/
drwxr-xr-x 1 root   root    306 Jul 23 12:22 root/
drwxrwxrwx 1 root   root     96 Aug  2 11:43 var_tmp/
# ls -l /mnt/rootvol/snapshot
drwxr-xr-x 1 root   root     36 Jul 30 22:27 home.20200730T2301/
drwxr-xr-x 1 root   root     36 Jul 30 22:27 home.20200731T0001/
drwxr-xr-x 1 root   root     36 Jul 30 22:27 home.20200801T2201/
drwxr-xr-x 1 root   root    306 Jul 23 12:22 root.20200730T0001/
drwxr-xr-x 1 root   root    306 Jul 23 12:22 root.20200731T0001/
drwxr-xr-x 1 root   root    306 Jul 23 12:22 root.20200802T1401/

For an extensive guide how to manage subvolumes, there is a SysAdminGuide over at kernel.org's btrfs wiki.

GRUB / Boot loader[edit | edit source]

Different Linux distributions have different ways to setup initramfs and grub. Please refer to your specific distribution's manual.

Further Reading[edit | edit source]

The official Btrfs wiki is a good resource to further your knowledge of Btrfs