3 Managing the Btrfs File System

This chapter describes tasks for administering the Btrfs file system in Oracle Linux.

About the Btrfs File System

The btrfs file system is designed to meet the expanding scalability requirements of large storage subsystems. As the btrfs file system uses B-trees in its implementation, its name derives from the name of those data structures, although it is not a true acronym. A B-tree is a tree-like data structure that enables file systems and databases to efficiently access and update large blocks of data no matter how large the tree grows.

The btrfs file system provides the following important features:
  • Copy-on-write functionality allows you to create both readable and writable snapshots, and to roll back a file system to a previous state, even after you have converted it from an ext3 or ext4 file system.

  • Checksum functionality ensures data integrity.

  • Transparent compression saves disk space.

  • Transparent defragmentation improves performance.

  • Integrated logical volume management allows you to implement RAID 0, RAID 1, or RAID 10 configurations, and to dynamically add and remove storage capacity.

Note:

Configuring a swap file on a btrfs file system is not supported.

You can find more information about the btrfs file system at https://btrfs.wiki.kernel.org/index.php/Main_Page.

Modifying a Btrfs File System

The following table shows how you can use the btrfs command to add or remove devices, and to rebalance the layout of the file system data and metadata across the devices.
Command Description

btrfs device adddevicemountpoint

Add a device to the file system that is mounted on the specified mount point. For example:

btrfs device add /dev/sdd /myfs

btrfs device deletedevicemountpoint

Remove a device from a mounted file system. For example:

btrfs device delete /dev/sde /myfs

btrfs device delete missingmountpoint

Remove a failed device from the file system that is mounted in degraded mode. For example:

btrfs device remove missing /myfs

To mount a file system in degraded mode, specify the -o degraded option to the mount command.

For a RAID configuration, if the number of devices would fall below the minimum number that are required, you must add the replacement device before removing the failed device.

btrfs filesystem balancemountpoint

After adding or removing devices, redistribute the file system data and metadata across the available devices.

Compressing and Defragmenting a Btrfs File System

You can compress a btrfs file system to increase its effective capacity, and you can defragment it to increase I/O performance.

To enable compression of a btrfs file system, specify one of the following mount options:
Mount Option Description

compress=lzo

Use LZO compression.

compress=zlib

Use zlib compression.

LZO offers a better compression ratio, while zlib offers faster compression.

You can also compress a btrfs file system at the same time that you defragment it.

To defragment a btrfs file system, use the following command:
sudo btrfs filesystem defragment filesystem_name
To defragment a btrfs file system and compress it at the same time:
sudo btrfs filesystem defragment -c filesystem_name
You can also defragment, and optionally compress, individual file system objects, such as directories and files, within a btrfs file system.
# btrfs filesystem defragment [-c] file_name ...

Note:

You can set up automatic defragmentation by specifying the autodefrag option when you mount the file system. However, automatic defragmentation is not recommended for large databases or for images of virtual machines.

Defragmenting a file or a subvolume that has a copy-on-write copy results breaks the link between the file and its copy. For example, if you defragment a subvolume that has a snapshot, the disk usage by the subvolume and its snapshot will increase because the snapshot is no longer a copy-on-write image of the subvolume.

Resizing a Btrfs File System

You can use the btrfs command to increase the size of a mounted btrfs file system if there is space on the underlying devices to accommodate the change, or to decrease its size if the file system has sufficient available free space. The command does not have any effect on the layout or size of the underlying devices.

For example, to increase the size of /mybtrfs1 by 2 GB:
sudo btrfs filesystem resize +2g /mybtrfs1
Decrease the size of /mybtrfs2 by 4 GB:
sudo btrfs filesystem resize -4g /mybtrfs2
Set the size of /mybtrfs3 to 20 GB:
sudo btrfs filesystem resize 20g /mybtrfs3

Creating Subvolumes and Snapshots

The top level of a btrfs file system is a subvolume consisting of a named b-tree structure that contains directories, files, and possibly further btrfs subvolumes that are themselves named b-trees that contain directories and files, and so on. To create a subvolume, change directory to the position in the btrfs file system where you want to create the subvolume and enter the following command:

sudo btrfs subvolume create subvolume_name

Snapshots are a type of subvolume that records the contents of their parent subvolumes at the time that you took the snapshot. If you take a snapshot of a btrfs file system and do not write to it, the snapshot records the state of the original file system and forms a stable image from which you can make a backup. If you make a snapshot writable, you can treat it as a alternate version of the original file system. The copy-on-write functionality of btrfs file system means that snapshots are quick to create, and consume very little disk space initially.

Note:

Taking snapshots of a subvolume is not a recursive process. If you create a snapshot of a subvolume, every subvolume or snapshot that the subvolume contains is mapped to an empty directory of the same name inside the snapshot.

The following table shows how to perform some common snapshot operations:
Command Description

btrfs subvolume snapshotpathnamepathname/snapshot_path

Create a snapshot snapshot_path of a parent subvolume or snapshot specified by pathname. For example:

btrfs subvolume snapshot /mybtrfs /mybtrfs/snapshot1

btrfs subvolume listpathname

List the subvolumes or snapshots of a subvolume or snapshot specified by pathname. For example:

btrfs subvolume list /mybtrfs

Note:

You can use this command to determine the ID of a subvolume or snapshot.

btrfs subvolume set-defaultIDpathname

By default, mount the snapshot or subvolume specified by its ID instead of the parent subvolume. For example:

btrfs subvolume set-default 4 /mybtrfs

btrfs subvolume get-defaultpathname

Displays the ID of the default subvolume that is mounted for the specified subvolume. For example:

btrfs subvolume get-default /mybtrfs

You can mount a btrfs subvolume as though it were a disk device. If you mount a snapshot instead of its parent subvolume, you effectively roll back the state of the file system to the time that the snapshot was taken. By default, the operating system mounts the parent btrfs volume, which has an ID of 0, unless you use set-default to change the default subvolume. If you set a new default subvolume, the system will mount that subvolume instead in future. You can override the default setting by specifying either of the following mount options:
Mount Option Description

subvolid=snapshot-ID

Mount the subvolume or snapshot specified by its subvolume ID instead of the default subvolume.

subvol=pathname/snapshot_path

Mount the subvolume or snapshot specified by its pathname instead of the default subvolume.

Note:

The subvolume or snapshot must be located in the root of the btrfs file system.

When you have rolled back a file system by mounting a snapshot, you can take snapshots of the snapshot itself to record its state.

When you no longer require a subvolume or snapshot, use the following command to delete it:
sudo btrfs subvolume delete subvolume_path

Note:

Deleting a subvolume deletes all subvolumes that are below it in the b-tree hierarchy. For this reason, you cannot remove the topmost subvolume of a btrfs file system, which has an ID of 0.

For details of how to use the snapper command to create and manage btrfs snapshots, see Using snapper with Btrfs Subvolumes.

Using snapper with Btrfs Subvolumes

You can use the snapper utility to create and manage snapshots of btrfs subvolumes.

To set up the snapper configuration for an existing mounted btrfs subvolume:

sudo snapper -c config_name create-config -f btrfs fs_name

Here config_name is the name of the configuration and fs_name is the path of the mounted btrfs subvolume. The command adds an entry for config_name to /etc/sysconfig/snapper, creates the configuration file /etc/snapper/configs/config_name , and sets up a .snapshots subvolume for the snapshots.

For example, the following command sets up the snapper configuration for a btrfs root file system:

sudo snapper -c root create-config -f btrfs /

By default, snapper sets up a cron.hourly job to create snapshots in the .snapshot subdirectory of the subvolume and a cron.daily job to clean up old snapshots. You can edit the configuration file to disable or change this behavior. For more information, see the snapper-configs(5) manual page.

There are three types of snapshot that you can create using snapper:

post

You use a post snapshot to record the state of a subvolume after a modification. A post snapshot should always be paired with a pre snapshot that you take immediately before you make the modification.

pre

You use a pre snapshot to record the state of a subvolume before a modification. A pre snapshot should always be paired with a post snapshot that you take immediately after you have completed the modification.

single

You can use a single snapshot to record the state of a subvolume but it does not have any association with other snapshots of the subvolume.

For example, the following commands create pre and post snapshots of a subvolume:

sudo snapper -c config_name create -t pre -p N
... Modify the subvolume's contents...
sudo snapper -c config_name create -t post --pre-num N -p N'

The -p option causes snapper to display the number of the snapshot so that you can reference it when you create the post snapshot or when you compare the contents of the pre and post snapshots.

To display the files and directories that have been added, removed, or modified between the pre and post snapshots, use the status subcommand:

sudo snapper -c config_name status N .. N'

To display the differences between the contents of the files in the pre and post snapshots, use the diff subcommand:

sudo snapper -c config_name diff N .. N'

To list the snapshots that exist for a subvolume:

sudo snapper -c config_name list

To delete a snapshot, specify its number to the delete subcommand:

sudo snapper -c config_name delete N''

To undo the changes in the subvolume from post snapshot N' to pre snapshot N:

sudo snapper -c config_name undochange N..N'

For more information, see the snapper(8) manual page.

Cloning Virtual Machine Images and Linux Containers

You can use a btrfs file system to provide storage space for virtual machine images and Linux Containers. The ability to quickly clone files and create snapshots of directory structures makes btrfs an ideal candidate for this purpose. For details of how to use the snapshot feature of btrfs to implement Linux Containers, see Linux Containers in Oracle Linux 7: Working With LXC.

Using the Send/Receive Feature

Note:

The send/receive feature requires that you boot the system using UEK R3.

The send operation compares two subvolumes and writes a description of how to convert one subvolume (the parent subvolume) into the other (the sent subvolume). You would usually direct the output to a file for later use or pipe it to a receive operation for immediate use.

The simplest form of the send operation writes a complete description of a subvolume:

sudo btrfs send [-v] [-f] [sent_file] ... subvol

You can specify multiple instances of the -v option to display increasing amounts of debugging output. The -f option allows you to save the output to a file. Both of these options are implicit in the following usage examples.

The following form of the send operation writes a complete description of how to convert one subvolume into another:

sudo btrfs send -p parent_subvol sent_subvol

If a subvolume such as a snapshot of the parent volume, known as a clone source, will be available during the receive operation from which some of the data can be recovered, you can specify the clone source to reduce the size of the output file:

sudo btrfs send [-p parent_subvol] -c clone_src [-c clone_src] ... subvol

You can specify the -c option multiple times if there is more than one clone source. If you do not specify the parent subvolume, btrfs chooses a suitable parent from the clone sources.

You use the receive operation to regenerate the sent subvolume at a specified path:

sudo btrfs receive [-f sent_file] mountpoint

How to Use Send/Receive to Implement Incremental Backups

The following procedure is a suggestion for setting up an incremental backup and restore process for a subvolume.

  1. Create a read-only snapshot of the subvolume to serve as an initial reference point for the backup:

    sudo btrfs subvolume snapshot -r /vol /vol/backup_0
  2. Run sync to ensure that the snapshot has been written to disk:

    sudo sync
  3. Create a subvolume or directory on a btrfs file system as a backup area to receive the snapshot, for example, /backupvol.

  4. Send the snapshot to /backupvol:

    sudo btrfs send /vol/backup_0 | btrfs receive /backupvol

    This command creates the subvolume /backupvol/backup_0.

    Having created the reference backup, you can then create incremental backups as required.

  5. To create an incremental backup:

    1. Create a new snapshot of the subvolume:

      sudo btrfs subvolume snapshot -r /vol /vol/backup_1
    2. Run sync to ensure that the snapshot has been written to disk:

      sudo sync
    3. Send only the differences between the reference backup and the new backup to the backup area:

      sudo btrfs send -p /vol/backup_0 /vol/backup_1 | btrfs receive /backupvol

      This command creates the subvolume /backupvol/backup_1.

Using Quota Groups

Note:

The quota groups feature requires that you boot the system using UEK R3.

To enable quotas, use the following command on a newly created btrfs file system before any creating any subvolumes:

sudo btrfs quota enable volume

To assign a quota-group limit to a subvolume, use the following command:

sudo btrfs qgroup limit size /volume/subvolume

For example:

sudo btrfs qgroup limit 1g /myvol/subvol1
sudo btrfs qgroup limit 512m /myvol/subvol2

To find out the quota usage for a subvolume, use the btrfs qgroup show path command:

Replacing Devices on a Live File System

Note:

The device replacement feature requires that you boot the system using UEK R3.

You can replace devices on a live file system. You do not need to unmount the file system or stop any tasks that are using it. If the system crashes or loses power while the replacement is taking place, the operation resumes when the system next mounts the file system.

Use the following command to replace a device on a mounted btrfs file system:

sudo btrfs replace start source_dev target_dev [-r] mountpoint

source_dev and target_dev specify the device to be replaced (source device) and the replacement device (target device). mountpoint specifies the file system that is using the source device. The target device must be the same size as or larger than the source device. If the source device is no longer available or you specify the -r option, the data is reconstructed by using redundant data obtained from other devices (such as another available mirror). The source device is removed from the file system when the operation is complete.

You can use the btrfs replace status mountpoint and btrfs replace cancel mountpoint commands to check the progress of the replacement operation or to cancel the operation.

Creating Snapshots of Files

You can use the --reflink option to the cp command to create lightweight copies of a file within the same subvolume of a btrfs file system. The copy-on-write mechanism saves disk space and allows copy operations to be almost instantaneous. The btrfs file system creates a new inode that shares the same disk blocks as the existing file, rather than creating a complete copy of the file's data or creating a link that points to the file's inode. The resulting file appears to be a copy of the original file, but the original data blocks are not duplicated. If you subsequently write to one of the files, the btrfs file system makes copies of the blocks before they are written to, preserving the other file's content.

For example, the following command creates the snapshot bar of the file foo:
sudo cp -reflink foo bar

About the Btrfs root File System

Oracle Linux 7 installation allows you to create a btrfs root file system. The mounted root file system is a snapshot (named install) of the root file system taken at the end of installation. To find out the ID of the parent of the root file system subvolume, use the following command:
sudo btrfs subvolume list /
ID 258 top level 5 path install 

In this example, the installation root file system subvolume has an ID of 5. The subvolume with ID 258 (install) is currently mounted as /. Figure 3-1 illustrates the layout of the file system:

Figure 3-1 Layout of the root File System Following Installation


The diagram illustrates the layout of the example root file system with the top level subvolume (ID 5) containing the root file system as it existed after installation and the subvolume install (ID 258) containing the currently active root file system.

The top-level subvolume with ID 5 records the contents of the root file system file system at the end of installation. The default subvolume (install) with ID 258 is currently mounted as the active root file system.

The mount command shows the device that is currently mounted as the root file system:
sudo mount
/dev/mapper/vg_btrfs-lv_root on / type btrfs (rw)
...
To mount the installation root file system volume, you can use the following commands:
sudo mkdir /instroot
sudo mount -o subvolid=5 /dev/mapper/vg-btrfs-lv-root /instroot
If you list the contents of /instroot, you can see both the contents of the installation root file system volume and the install snapshot, for example:
ls /instroot
bin   cgroup  etc   install  lib64  misc  net  proc  sbin     srv  tmp  var
boot  dev     home  lib      media  mnt   opt  root  selinux  sys  usr
The contents of / and /instroot/install are identical as demonstrated in the following example where a file (foo) created in /instroot/install is also visible in /:
touch /instroot/install/foo
ls /
bin   cgroup  etc  home      lib    media  mnt  opt   root  selinux  sys  usr 
boot  dev     foo  instroot  lib64  misc   net  proc  sbin  srv      tmp  var
ls /instroot/install
bin   cgroup  etc  home      lib    media  mnt  opt   root  selinux  sys  usr 
boot  dev     foo  instroot  lib64  misc   net  proc  sbin  srv      tmp  var
rm -f /foo
ls /
bin   cgroup  etc   instroot  lib64  misc  net  proc  sbin     srv  tmp  var
boot  dev     home  lib       media  mnt   opt  root  selinux  sys  usr
# ls /instroot/install
bin   cgroup  etc   instroot  lib64  misc  net  proc  sbin     srv  tmp  var
boot  dev     home  lib       media  mnt   opt  root  selinux  sys  usr

Creating Snapshots of the root File System

To take a snapshot of the current root file system:
  1. Mount the top level of the root file system on a suitable mount point.
    sudo mount -o subvolid=5 /dev/mapper/vg-btrfs-lv-root /mnt
  2. Change directory to the mount point and take the snapshot. In this example, the install subvolume is currently mounted as the root file system system.
    cd /mnt
    sudo btrfs subvolume snapshot install root_snapshot_1
    Create a snapshot of 'install' in './root_snapshot_1'
  3. Change directory to / and unmount the top level of the file system.
    # cd /
    # umount /mnt
    The list of subvolumes now includes the newly created snapshot.
    sudo btrfs subvolume list /
    ID 258 top level 5 path install
    ID 260 top level 5 path root_snapshot_1

Mounting Alternate Snapshots as the root File System

If you want to roll back changes to your system, you can mount a snapshot as the root file system by specifying its ID as the default subvolume, for example:
sudo btrfs subvolume set-default 260 /
Reboot the system for the change to take effect.

Deleting Snapshots of the root File System

To delete a snapshot:
  1. Mount the top level of the file system, for example:
    sudo mount -o subvolid=5 /dev/mapper/vg-btrfs-lv-root /mnt
  2. Change directory to the mount point and delete the snapshot.
    cd /mnt
    sudo btrfs subvolume delete install
    Delete subvolume '/mnt/install'
  3. Change directory to / and unmount the top level of the file system.
    cd /
    sudo umount /mnt
    The list of subvolumes now does not include install.
    sudo btrfs subvolume list /
    =ID 260 top level 5 path root_snapshot_1