Introduction: Working With Btrfs

Btrfs is an emerging file system standard for Linux, and it has many benefits over ext3 and 4.

A few of the benefits of btrfs include...

  • Snapshots - the ability to freeze the file system in time and revert back to that state
  • Subvolumes - work closely with snapshots, allows you to create dynamic "partitions"
  • Online partition resizing - you can resize partitions (both shrink and grow) while they are mounted, even the operating system partition
  • Quotas, the ability to assign maximum sizes for subvolumes (I do not

You need:

  • A computer (note that you will have to erase the hard drive)
  • A second computer for research (the one you are working on will not always be bootable)
  • A Gparted live CD/USB
  • A Linux distro that it up to date (Ubuntu 14.04 and its derivatives, Fedora, Debian (backport kernel recommended), Linux Mint, etc), live is not necessary
  • A lot of patience
  • A backup destination (I used my SFTP server, but an external hard drive will work fine)
  • A lot of time

I assume you already know:

  • How to make installer USB/CD's; Unetbootin doesn't work in all situations - it is easiest to use Gnome Disk Utility (called Disks in Ubuntu)
  • How to deal with disk partitions
  • Linux command line (Bash) basics, basic navigation and file management commands (mv, cp, ls, cd), I will be teaching you how to use btrfs-tools
  • Basic troubleshooting skills

WARNING: This should not brick your computer, but it may be rendered unbootable. Worst case scenario: you will likely need to create a new partition table and start from scratch.

WARNING: I am not dealing with Windows 8 in this Instructable, and I do not recommend you try to do this alongside Windows 8. You will end up dealing with a far more complicated boot system that has been configured in a very strange way. You will also probably have trouble doing this on a Mac. Long story short: it is recommended that this not be set up next to a proprietary system and that you start from scratch.

How Btrfs Works

Btrfs actually means "b-tree filesystem." A b-tree refers to the means by which data is stored, and is the same technology used to manage SQL databases and many other filesystems. It is beyond the realm of this Instructable to explain b-trees in detail. In summary: b-trees are extremely efficient when it comes to searching a hard drive. The idea is derived from a binary tree, in which each step in the search, half of the data is eliminated until what you are looking for is found. B-trees extend this by allowing you to eliminate an arbitrary amount of the data - instead of half, you are able to eliminate, say, 90% of the original dataset. However, there is a cost: b-trees are slower when it comes to insertion, deletion, and searches within small data. This is where a simple binary tree wins out: if the data can be stored entirely in RAM, the to read/write speed is much faster, therefore, the primary concern is minimizing the number of CPU checks to to run. B-trees require more CPU, but minimize data reading and writing.

Feel free to comment if you have questions, corrections, or suggestions.

Step 1: Gparted

Gparted is a very powerful partition editor for Linux/UNIX-based systems. You can learn all about it and download a live USB (which you will need if you are following these instructions) at http://www.gparted.org/. I am using it because it is easier and safer than Terminal in this case.

WARNING: the following operations will erase your hard drive. I am taking you up to the step that erases the drive (I was unable to save screenshots during the process).

  1. Boot into the Gparted Live CD
  2. Within Gparted, goto Device -> Create Partition Table...
  3. Here, you have several options
    • DOS/MBR: the traditional style of partition table.
      • MBR (Master Boot Record) works well with older hardware. If you are planning on installing Windows alongside Linux, it may be easier to configure. It has only recently been overtaken by GPT/UEFI with the advent of Windows 8.
      • The number of partitions MBR can handle is very limited
      • The maximum size drive it can address is 2TB.
    • GPT: GUID Partition Table is actually a part of the UEFI standard, it has several benefits...
      • More partitions
      • More addressable memory
      • Linux is capable of booting from GPT even on a BIOS-based system. Windows is not guaranteed to have this capability.
  4. Clicking OK will proceed to erase the hard drive
  5. You will need to create three partitions. However, it is best to create these during the OS installation.

Step 2: Resizing Partitions

It is fairly easy to resize partitions using Gparted. The images above provide a fairly easy walkthrough. I resized the OS partition from within the OS itself, which is a unique feature of btrfs.

Step 3: Moving Partitions

Moving partitions can be dangerous for many reasons, but sometimes it is necessary. Therefore, I have included instructions on how to do so.

There are two situations that will result in a partition being moved:

  1. Resizing at the front in either direction. Moving the front of a partition will always result in the whole partition being shifted.
  2. Moving the partition without resizing it. All of the data is copied, block by block, to another location - whether you are using the space within the partition or not.

Step 4: OS Installation Decisions

I am assuming you already know the basics of installing an operating system via GUI. This process is very easy with almost any Ubuntu-based system. At this point, the main concern is the partitioning step. In the case of both Ubuntu and Debian, you need to choose the manual option (Ubuntu calls it "Something Else").

Partitions, assuming that /dev/sda is the hard drive:

  • /dev/sda# bios_grub (1MB front)
  • /dev/sda# swap (2x RAM front)

Now, there are several options...

Everything in a single partition:

  • /dev/sda# btrfs (size > 4GB) mount point: /
    includes the home directory and everything else within that partition

Separate partitions: giving /home a separate partition

  • /dev/sda# btrfs (size > 4GB front) mount point: /

  • /dev/sda# btrfs (any size back) mount point: /home

Step 5: Separate / and /home Partitions

One common partition scheme used when installing Linux is to have separate partitions for the / and /home mount points. This works the same way with btrfs as it does setting up with any other filesystem. This is very easy to do during the OS installation.

If the OS partition becomes too small, expand it into the extra space. This is very easy to do from Gparted and btrfs allows you to easily grow or shrink the OS partition in place while the system is running - no need to boot into a live CD. However, because the home partition is at the end of the drive, it has to be moved back in order to expand. When you move the partition, it cannot be mounted. In addition, this takes a long time because all of the data has to be copied to the new location. Basically, the home partition is a pain to resize.

It is much easier to work with a single partition.

So, why would you want a partition layout like this? The answer is simple: with the home folder in a separate partition, you can easily install another Linux or UNIX-based system (excluding Mac because it uses its own proprietary filesystem) that uses that partition. In other words, you don't need multiple copies of the same files, and files you create in one system will be visible in the other.

Maybe subvolumes can make our lives a little easier...

Step 6: A Single Partition Using Subvolumes

This configuration is much easier during installation, just set btrfs as the filesystem where the OS is stored. Because no other partitions (except bios_grub and swap) were created, home will just be a folder. When the new system is booted, it may have already created a home subvolume, but if it didn't, it is easy to create.

To check for existing subvolumes, run the following command...

$ sudo btrfs list /

This command lists all of the subvolumes on the drive.

If a subvolume for home already exists, the output will look something like this...

ID 257 gen 5493 top level 5 path @
ID 268 gen 5493 top level 257 path home

If there is no home subvolume, the second line would not exist.

NOTE: The number after ID is a globally accessible identifier for the subvolume. You can use it in any current directory and do not have to supply a path. This can be useful in btrfs subvol commands as you do not have to change your current directory.

Step 7: Combining Partitions (combining / and /home Partitions Into One)

Let's say that you created or have a pre-existing separate /home partition (as set up in step 5) and you want to combine those partitions. This can be a very painstaking process if you try to make it more complex (as I originally attempted). Regardless, this is still a fairly complex process.

Here are the steps involved:

  1. Shrink the /home partition at the front. This is a situation where moving a partition is necessary.
  2. Enlarge the OS partition so that I can handle the data from the /home partition
  3. Copy the data to a btrfs subvolume (called newhome)
  4. Edit /etc/fstab
  5. Reboot the system, deal with the error
  6. Rename the newhome to home
  7. Reboot the system again, see troubleshooting if there is another error
  8. Delete the old home partition
#It will be necessary to run all of these actions as superuser
#running 'su' or 'sudo -i' will help.

root@computer:~# cd /

#3
root@computer:/# btrfs subvol create newhome
root@computer:/# cp home/* newhome/

#4, I used nano for editing, any plain text editor will work
root@computer:/# nano /etc/fstab<br>

Here are the contents and edits necessary for fstab. The text below is a generic example. Yours will not be identical. If you are not using GPT, then the file will look considerably different.

# /etc/fstab: static file system information.
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).

# / was on /dev/sda4 during installation
UUID=1d75f1d1-c062-4158-b8a7-8beaa7321031 / btrfs defaults,subvol=@ 0 1
UUID=another_hex_code /home btrfs defaults 0 1
#delete the above line (the one with /home as the mount point)

#swap
/dev/sda3 none swap sw 0 0

Now, reboot the system. One of two things will likely happen. Either (a) the system will fail to boot and will give you an option to launch a rescue terminal or (b) the system will boot completely and (assuming you open a terminal) a notice saying $HOME=/ will be at the top. Both of these conditions should be dealt with by using the command below.

#if the below command outputs an error because home is not empty, you did something wrong.
#if it outputs no such file or directory, just ignore it and move on
root@computer:/# rmdir home

#6
root@computer:/# mv newhome home

Finally, reboot the system. /home should now be a subvolume and have the same contents as the old partition. Run the below command, which should have something similar to the following output. This will show you that /home is in fact a subvolume.

root@computer:/# btrfs subvol list /
ID 257 gen 7186 top level 5 path @
ID 268 gen 7186 top level 257 path home

Go ahead and delete the former partition used for /home from Gparted. it may also be worth resizing your OS partition.

Reboot the system one last time, just to make sure.

Alternate method (untested): it may be possible to name your /home subvolume something other than home and make /home a symbolic link to that subvolume.

Step 8: Subvolumes

You have already worked with subvolumes some. This page is just a filler and talks about subvolumes in general. Below is an excerpt from the Btrfs manpage about actions that can be performed on a subvolume.

btrfs subvolume create [-i ] [/]
Create a subvolume
btrfs subvolume delete [...]
Delete subvolume(s)
btrfs subvolume list [options] [-G [+|-]value] [-C [+|-]value] [--sort=gen,ogen,rootid,path]
List subvolumes (and snapshots)
btrfs subvolume snapshot [-r] |[/]
btrfs subvolume snapshot [-r] [-i ] |[/]
btrfs subvolume get-default
Get the default subvolume of a filesystem
btrfs subvolume set-default
Set the default subvolume of a filesystem
btrfs subvolume find-new
List the recently modified files in a filesystem
btrfs subvolume show
Show more information of the subvolume

You can find more information about these commands by entering btrfs subvol command --help. Note that you can either enter subvol or subvolume - they do the same things.

Subvolumes are fairly easy to use, and you interact with them as if they are folders for any day-to-day actions. The only difference is that the btrfs filesystem recognizes subvolumes in a special way - which allows you to take snapshots.

Step 9: Snapshots

Here is the manpage excerpt for snapshots:

btrfs subvolume snapshot [-r] |[/]
Create a snapshot of the subvolume
Create a writable/readonly snapshot of the subvolume with the name in the directory. If only is given, the subvolume will be named the basename of .
-r create a readonly snapshot

At this point, my knowledge of the inner workings of snapshots is fairly limited. However, I will write down the observations I have made so far:

  • The output of the command is another subvolume (possibly read-only)
  • When you make a snapshot, the disk space is allocated for it, but the data is not copied
  • Instead of copying the data, it appears that the changes from the original are tracked and logged (if the original is deleted, the remaining data is most likely copied, but I have not tested this theory)
  • Assuming you have a copy of the dataset, snapshots can build upon each other - that is, instead of having a lot of duplicate data in a backup, you can have a list of snapshots that log the changes after each backup period. If these build upon each other (snapshots of snapshots, basically creating a linked list), it should be far more efficient than storing copies of the data. Again, this is untested by me at the time of writing.
  • The initial creation of a snapshot is almost instantaneous, no data is copied.

Step 10: Troubleshooting

I cannot provide a comprehensive guide to every problem you may encounter, however, I will talk about the issues that I ran into.

Problems with /etc/fstab

WARNING: /etc/fstab can be dangerous to edit! It may cause your computer to generate a black hole of which it is the singularity.

/etc/fstab manages what volumes are mounted on boot.

I really can't help you much here. However, I will offer this advice: only mess with the /home partition. If you do mess up, you will know, and it is often recoverable. Do not lose the UUID of the /home partition (if it exists). At one point (after hours of work), I was able mount a subvolume not named home as /home, but it was very difficult.

Errors within the btrfs filesystem

All of the btrfs-related errors have been easy for me to fix. You will know when there are errors because you won't be able to move or resize the filesystem. Btrfs has some error removal facilities built in. I have used a few of them. NOTE: these operations must be run when the partition is UNMOUNTED. I will demonstrate via the GParted live CD.

In order to check for errors, run btrfs check.

root@debian:~# btrfs check /dev/sda4

...

Note that the first time around I do not try to repair the errors. I did have a screenshot showing the errors that existed, but that screenshot was erased for some reason. Basically, it had some cache warnings and "inode" issues.

If there are errors, first try running the following... I have commented the errors that were repaired.

root@debian:~# btrfs check --repair /dev/sda4
enabling repair mode Checking filesystem on /dev/sda4 UUID: 1d75f1d1-c062-4158-b8a7-8beaa7321031 checking extents checking free space cache cache and super generation don't match, space cache will be invalidated #A bunch of other cache-related errors were fixed above this point. checking fs roots reset isize for dir 149389 root 257 #FIXED reset isize for dir 19918 root 268 #FIXED Segmentation fault

The final line, Segmentation fault, is not good. It means that the program tried to access memory that never existed or no longer exists. I am not too concerned with this, it should not have caused any permanent damage. At this point, I don't know if all of the errors were fixed, so I am going to run another check.

root@debian:~# btrfs check /dev/sda4
Checking filesystem on /dev/sda4 UUID: 1d75f1d1-c062-4158-b8a7-8beaa7321031 checking extents checking free space cache cache and super generation don't match, space cache will be invalidated checking fs roots checking csums checking root refs found 41505193481 bytes used err is 0 total csum bytes: 74484016 total tree bytes: 587497472 total fs tree bytes: 455458816 total extent tree bytes: 40435712 btree space waste bytes: 106796567 file data blocks allocated: 1204523626496 referenced 71484911616 Btrfs v3.14.1

The above output means that the filesystem was fine. It should be resizeable in this state. However, I am not sure what "cache and super generation don't match" means - it has not caused me any trouble.

At times, the --repair argument cannot fix the problems automatically. I have encountered this several times in the past. The set of commands below can help in this situation. The output of this command is fairly long, so you will have to scroll to find the excerpt.

root@debian:~# btrfs --help
...
btrfs inspect-internal inode-resolve [-v]  
Get file system paths for the given inode
btrfs inspect-internal logical-resolve [-Pv] [-s bufsize] Get file system paths for the given logical address btrfs inspect-internal subvolid-resolve Get file system paths for the given subvolume ID. btrfs inspect-internal rootid Get tree ID of the containing subvolume of path.
...