3 Managing the Btrfs File System
The Btrfs file system is designed to meet the expanding scalability requirements of large storage subsystems. Because the Btrfs file system uses B-trees in its implementation, its name is derived 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, irrespective of how large the tree grows.
The Btrfs file system provides the following important features:
-
Copy-on-write functionality, which enables you to create both readable and writable snapshots and roll back a file system to a previous state, even after converting it from an
ext3
orext4
file system. -
Checksum functionality, which ensures data integrity.
-
Snapshots send and receive for remote incremental backups.
-
Transparent compression, which saves disk space.
-
Transparent defragmentation for improved performance.
-
Integrated, logical volume management, which enables you to implement RAID 0, RAID 1, RAID 10, RAID1C3 or RAID1C4 configurations, and dynamically add or remove storage capacity.
For more information, visit https://btrfs.wiki.kernel.org/.
For an overview of local file system management, see About File System Management.
Note:
In Oracle Linux 9, the Btrfs file system type, as well as all of the features that are documented in this chapter is supported on the Unbreakable Enterprise Kernel (UEK) release only. Working with Btrfs file system features requires that you boot the system by using UEK R7.
Setting Up and Administering a Btrfs File System
This section describes procedures to create a Btrfs file system as well as administering it for a more efficient use.
Creating a Btrfs File System
Note:
Note that the /sbin/mkfs.* tool is not
provided by the same package as the kernel modules that are
required by the btrfs command. Use the
modinfo btrfs command to check whether
the btrfs module is available in the kernel that is booted.
Also, if the btrfs-progs
package is not
installed on your system, you will need to install it.
You can use the mkfs.btrfs command to create a Btrfs file system that is laid out across one or more block devices. The default configuration is to mirror the filesystem metadata across the devices. If you specify a single device, the metadata is duplicated on that device, unless you specify to use only one copy of the metadata. The devices can be whole block device(s), simple disk partitions, files, loopback devices (that is, disk images in memory), multipath devices, or LUNs that implement RAID in hardware.
See the mkfs.btrfs(8)
manual page for more
detailed information about the mkfs.btrfs
command the various Btrfs configurations that you can create.
When you want to mount the file system, you can specify it by any of its component devices, for example:
sudo mkfs.btrfs -d raid10 -m raid10 /dev/sd[fghijk]
sudo mount /dev/sdf mountpoint
The mkfs.btrfs command automatically scans the new Btrfs devices into the kernel. To scan and assemble all of the relevant devices of the volume in the kernel you need to run the btrfs device scan command. You can undo this action by using the btrfs device scan --forget command. To assemble all of the relevant devices of the volume, you might need to run the btrfs device scan command.
You can obtain the RAID configuration for a mounted
btrfs
file system as follows:
sudo btrfs filesystem df mountpoint
Note that the btrfs filesystem df command displays more accurate information about the space that is used by a Btrfs file system than by using the df command.
You can also use the btrfs filesystem usage
command to display information about all of the
btrfs
file systems that are on a system, for
example:
sudo btrfs filesystem usage /btrfs
Overall: Device size: 1.95TiB Device allocated: 5.03GiB Device unallocated: 1.95TiB Device missing: 0.00B Used: 256.00KiB Free (estimated): 999.48GiB (min: 999.48GiB) Data ratio: 2.00 Metadata ratio: 2.00 Global reserve: 3.25MiB (used: 0.00B) Data,RAID10: Size:2.00GiB, Used:0.00B (0.00%) /dev/nvme0n1p6 1.00GiB /dev/nvme0n1p7 1.00GiB /dev/nvme0n1p8 1.00GiB /dev/nvme0n1p9 1.00GiB Metadata,RAID10: Size:512.00MiB, Used:112.00KiB (0.02%) /dev/nvme0n1p6 256.00MiB /dev/nvme0n1p7 256.00MiB /dev/nvme0n1p8 256.00MiB /dev/nvme0n1p9 256.00MiB System,RAID10: Size:16.00MiB, Used:16.00KiB (0.10%) /dev/nvme0n1p6 8.00MiB /dev/nvme0n1p7 8.00MiB /dev/nvme0n1p8 8.00MiB /dev/nvme0n1p9 8.00MiB Unallocated: /dev/nvme0n1p6 498.74GiB /dev/nvme0n1p7 498.74GiB /dev/nvme0n1p8 498.74GiB /dev/nvme0n1p9 498.74GiB
Modifying a Btrfs File System
You can use the btrfs command to add or remove devices and rebalance the layout of the file system data and metadata across devices. The following table describes each of the commands that can use to perform these tasks.
Command | Description |
---|---|
btrfs device add device mountpoint |
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 delete device mountpoint |
Remove a device from a mounted file system, for example: btrfs device delete /dev/sde /myfs |
btrfs device delete missing mountpoint |
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 balance mountpoint |
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, as well as defragment it to increase I/O performance.
The following three compression types are supported:
-
zlib
-
lzo
-
zstd
There are three ways in which you can enable compression:
-
By using the subvolume property, for example:
sudo btrfs subvolume create /btrfs/sv1
sudo btrfs property set /btrfs/sv1 compression zstd
-
By using the mount option in one of the following ways:
Use the
lzo
type to compress the file data on the whole file system:sudo mount -o compress=lzo /dev/sdb /btrfs
Use the
zstd
type to compress a subvolume and then mount it at the/btrfs1
mount point:sudo mount -o compress=zstd,subvolume=sv1 /devsdb /btrfs1
-
By using defragment, for example:
sudo btrfs filesystem defragment -czlib /btrfs1/akzo
You can enable compression at any point and only the new writes are compressed or defragmentation is run.
You can 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, use the following command:
sudo btrfs filesystem defragment -c filesystem_name
You can use the following command to defragment and optionally compress individual file system objects such as directories and files within a Btrfs file system:
sudo btrfs filesystem defragment [-c] file_name ...
To set up automatic defragmentation, specify the autodefrag option when you mount the file system. However, note that automatic defragmentation is not recommended for large databases or for images of virtual machines.
Note:
Defragmenting a file or a subvolume with a copy-on-write copy 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 as long as there is space on the underlying devices to accommodate the change. You also use the btrfs command to decrease its size, if the file system has sufficient available free space. Note that running the command does not have any effect on the layout or size of the underlying devices.
You would increase the size of /mybtrfs1
by 2
GB as follows:
sudo btrfs filesystem resize +2g /mybtrfs1
The following example shows how to set the size of
/mybtrfs3
to 20 GB:
sudo btrfs filesystem resize 20g /mybtrfs3
The following command decreases the size of
/mybtrfs2
by 4 GB:
sudo btrfs filesystem resize -4g /mybtrfs2
Creating Subvolumes and Snapshots
The top level of a Btrfs file system is a subvolume consisting of
a named b-tree structure containing directories, files, and
possibly further btrfs
subvolumes that are also
named b-trees, each of which also contains directories and files,
and so on.
To create a subvolume, change directories to the position in the
btrfs
file system for which you want to create
the subvolume, then run the following command:
sudo btrfs subvolume create subvolume_name
Snapshots are a type of subvolume that record 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 a btrfs
file system means that
snapshots are created quickly 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 that snapshot.
The following table describes commands to use to perform some common snapshot operations.
Command | Description |
---|---|
btrfs subvolume snapshot pathname pathname / 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 list pathname |
List the subvolumes or snapshots of a subvolume or snapshot that is 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-default ID pathname |
By default, mount the snapshot or subvolume that is specified by its ID instead of the parent subvolume, for example: btrfs subvolume set-default 4 /mybtrfs |
btrfs subvolume get-default pathname |
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 when the
snapshot was taken. By default, the operating system mounts the
parent Btrfs volume, which has an ID of 0
,
unless you use the set-default option to change
the default subvolume. If you set a new default subvolume, the
system mounts that subvolume going forward. You can override the
default setting by specifying any of the mount
options that are described in the following table.
Mount Option | Description |
---|---|
subvolid= snapshot-ID |
Mount the subvolume or snapshot that is specified by its subvolume ID instead of the default subvolume. |
subvol= pathname / snapshot_path |
Mount the subvolume or snapshot that is 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. |
After you have rolled back a file system by mounting a snapshot, you can take snapshots of the snapshot to record its state.
When you no longer require a subvolume or snapshot, you can delete it as follows:
sudo btrfs subvolume delete subvolume_path
Deleting a subvolume deletes all of the subvolumes under 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 information about using the snapper command to create and manage Btrfs snapshots, see Automating File System Snapshots With the Snapper Utility.
Attention:
Snapshots record the state of the file system at a moment in time. As such, it is not possible to guarantee file system integrity for transactional processes that may have been in operation at the time when a snapshot was taken. While utilities like the snapper command may help to capture before and after snapshots for particular operations, such as when using the dnf command, these snapshots are still unaware of other processes that may be running on the system at the same time. If you have processes that may have intensive I/O or memory usage, such as database or middleware applications, you should stop these or ensure that all activity is complete before taking a snapshot to help to reduce the likelihood of data integrity or file system corruption issues within the snapshot.
Creating Swap Files on a Btrfs File System
Swap space is used in Oracle Linux when the amount of physical memory (RAM) is full. If the system needs more memory resources, and the RAM is full, inactive pages in memory are moved to the swap space. Although swap space is helpful for systems with a small amount of RAM, don't use swap space as a replacement for more RAM. You can allocate swap space to a dedicated swap partition, which is the recommended method. Or, you can use a swap file; or, you can combine the use of swap partitions and swap files.
Swap files in Btrfs are supported with the following limitations:
-
A swap file can't be on a snapshotted subvolume. Instead, we recommend that you create a subvolume on which to place the swap file.
-
Btrfs doesn't support swap files on file systems that span several devices.
The following are step-by-step instructions for creating a swap file in Btrfs. Before creating the new swap file, calculate the size of the swap file in MB. Then, multiply that number by 1024 to find the number of blocks the file requires. For example, the block size of a 64 MB swap file is 65536.
-
Create an empty file, for example:
sudo dd if=/dev/zero of=/swapfile bs=1024 count=65536
-
Set up the swap file by running the following command:
sudo mkswap /swapfile
-
Change the permissions on the file so that it's not world readable:
sudo chmod 0600 /swapfile
-
Enable the swap file at boot time by editing the
/etc/fstab
file as theroot
user to include the following entry:/swapfile swap swap defaults 0 0
-
Regenerate the mount units and register the new configuration in the
/etc/fstab
file:sudo systemctl daemon-reload
-
Activate the new swap file:
sudo swapon /swapfile
Running the previous command activates the new swap file immediately.
Or, you can run the following command to test whether the new swap file was successfully created by inspecting the active swap space:
sudo cat /proc/swaps
sudo free -h
Creating Backups and Using the Btrfs Send/Receive Feature
Note:
Working with the Btrfs send/receive feature requires that you boot the system by using UEK R7..
The send operation compares two subvolumes and writes a description of how to convert one subvolume, the parent subvolume, into the other subvolume, which is 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, for example:
sudo btrfs send [-v] [-f sent_file] ... subvol
You can specify many instances of the -v option to display increasing amounts of debugging output. The -f option is used to save the output to a file. Note that 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 to another subvolume:
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 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] ... subvol
You can specify the -c option for each of the clone source that exist. If you don't specify the parent subvolume, btrfs chooses a suitable parent from the clone sources.
Use the receive operation to regenerate the sent subvolume at a specified path, for example:
sudo btrfs receive [-f sent_file] mountpoint
Creating a Reference Backup in Preparation for Creating an Incremental Backup
The following procedure describes how to create a reference backup, which is a prerequisite to setting up an incremental backup and restore process for a subvolume by using the send/receive feature.
-
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
-
Ensure that the snapshot has been written to disk by running the sync command.
sudo sync
-
Create a subvolume or directory on a Btrfs file system as a backup area to receive the snapshot, for example,
/backupvol
. -
Send the snapshot to
/backupvol
.sudo btrfs send /vol/backup_0 | btrfs receive /backupvol
The previous command creates the
/backupvol/backup_0
subvolume.After creating the reference backup, you can then create incremental backups, as needed. See Creating an Incremental Backup.
Creating an Incremental Backup
The following instructions describe how to create an incremental backup by using the send/receive feature. Note that before creating an incremental backup, you must first create a reference backup. See Creating a Reference Backup in Preparation for Creating an Incremental Backup.
To create an incremental backup:
-
Create a snapshot of the subvolume.
sudo btrfs subvolume snapshot -r /vol /vol/backup_1
-
Ensure that the snapshot has been written to disk by running the sync command.
sudo sync
-
Send only the differences between the reference backup and the new backup to the backup area, for example:
sudo btrfs send -p /vol/backup_0 /vol/backup_1 | btrfs receive /backupvol
Running the previous comman creates the
/backupvol/backup_1
subvolume.
Managing Quotas for Btrfs Subvolumes With Quota Groups
Note:
Be aware that the quota groups feature is available as a Technology Preview only in Oracle Linux 9. Working with this feature requires that you boot the system by using UEK R7.
Enable quotas by running following command on a newly created Btrfs file system before any creating any subvolumes:
sudo btrfs quota enable volume
Assign a quota-group limit to a subvolume by using the following command:
sudo btrfs qgroup limit size /volume/subvolume
The following example shows how you would use this command:
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
You can replace devices on a live file system without unmounting the file system or stopping any tasks that are using the file system. If the system crashes or loses power while the replacement is taking place, the operation resumes when the system next mounts the file system.
To replace a device on a mounted Btrfs file system, use the following command:
sudo btrfs replace start source_dev target_dev [-r] mountpoint
In the previous command, source_dev and target_dev specify the source device to be replaced (source device) and the replacement device (target device). The mountpoint specifies the file system that is using the source device. The target device must be the same size 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 that is obtained from other devices,. such as another available mirror. The source device is removed from the file system when the operation is complete.
Use the btrfs replace status mountpoint command to check the progress of the replacement operation and the btrfs replace cancel mountpoint command to cancel the operation.
Creating Snapshots of Files
Use the cp command with the --reflink option 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 enables 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, you would create a snapshot named
bar
of a file named foo
as
follows:
cp -reflink foo bar
Automating File System Snapshots With the Snapper Utility
The Snapper utility can be used to automate the management of file system snapshots. The utility can make it easier to create and delete snapshots, while enabling users to compare the differences between snapshots and revert changes at the file level. For information about the Snapper utility, visit the upstream project page at http://snapper.io/.
Attention:
Snapshots record the state of the file system at a moment in time. As such, it is not possible to guarantee file system integrity for transactional processes that may have been in operation at the time when a snapshot was taken. While utilities like the snapper command may help to capture before and after snapshots for particular operations, such as when using the dnf command, these snapshots are still unaware of other processes that may be running on the system at the same time. If you have processes that may have intensive I/O or memory usage, such as database or middleware applications, you should stop these or ensure that all activity is complete before taking a snapshot to help to reduce the likelihood of data integrity or file system corruption issues within the snapshot.
If not already installed, you can install the Snapper utility from
the ol9_UEKR7
yum repository, by running:
sudo dnf install -y snapper
Creating a Snapper Configuration for a Subvolume
You can use the snapper command 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
In the previous command, config_name is the name of the configuration and fs_name is the path of the mounted Btrfs subvolume. Running the command does the following:
-
Adds an entry for config_name to the
/etc/sysconfig/snapper
file. -
Creates the configuration file
/etc/snapper/configs/config_name
. -
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 /
Use the snapper list-configs command to list all of the existing configurations:
sudo snapper list-configs
Config | Subvolume ------------+---------- home_config | /home root | /
Note:
The default snapper SELinux policy allows snapper to manage
snapshots in the /
,
/etc
, /mnt
,
/usr
, /var
and
HOME_ROOT
(usually
/home
). If you create a new directory, for
example /data
or /srv
.
You may need to set the SELinux file context for that
directory so that snapper can create and manage snapshots for
that directory. For example to enable snapper to manage
snapshots on the /data
directory, you can
run:
$ sudo semanage fcontext -a -t snapperd_data_t "/data/\.snapshots(/.*)?" $ sudo restorecon -R -v /data
Creating Different Types of Snapshots
You can create the following three types of snapshots by using the snapper command:
- 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 use a single snapshot to record the state of a subvolume but it does not have any association with other snapshots of the subvolume.
To create a single snapshot of a subvolume, use the snapper create command, for example:
sudo snapper -c config_name create --description "description"
Single snapshots are useful for periodic backup purposes and can also be used to create a back-up timeline, as described in Automatic Snapper Snapshots. For actions that are likely to result in specific file system modifications that you may need to roll back, you can use pre and post snapshots to capture snapshots of the file system before and after a transaction.
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'
Specifying the -p option with the
snapper command displays the number of the
snapshot so that you can reference it when creating the post
snapshot or when comparing the contents of the
pre
and post
snapshots.
Note that you can use the --command option
with the snapper command to wrap an operation
with pre
and post
snapshots. For example:
snapper -c root create --command "cd /tmp/build; make install" \ --description "Installing a home built binary"
Pre and post snapshots are frequently used when performing system changes that may be too complex to revert manually, such as when installing or upgrading packages. The DNF snapper plugin that is described in Automatic Snapper Snapshots uses pre and post snapshots in exactly this way and uses the description field to store the DNF transaction that triggered the snapshot.
For example, in the following set of snapshots, you can identify
periodic, single snapshots that are triggered as part of a
timeline and then a pre and post snapshot that is triggered by
the DNF snapper plugin when the vim
package
is installed.
$ sudo snapper -c root list
# | Type | Pre # | Date | User | Cleanup | Description | Userdata ---+--------+-------+------------------------------+------+----------+--------------------------+--------- 0 | single | | | root | | current | 1 | single | | Wed 25 Nov 2020 07:00:30 EST | root | timeline | timeline | 2 | single | | Wed 25 Nov 2020 08:00:01 EST | root | timeline | timeline | 3 | single | | Wed 25 Nov 2020 09:00:01 EST | root | timeline | timeline | 4 | pre | | Wed 25 Nov 2020 09:07:21 EST | root | number | /usr/bin/dnf install vim | 5 | post | 4 | Wed 25 Nov 2020 09:07:25 EST | root | number | /usr/bin/dnf install vim | 6 | single | | Wed 25 Nov 2020 10:00:01 EST | root | timeline | timeline |
Automatic Snapper Snapshots
By default, each snapper configuration
contains settings for a periodic backup, which is controlled by
the TIMELINE_CREATE
configuration variable in
the
/etc/snapper/configs/config_name
file. Automatic snapshots are triggered by a systemd timer unit
that you must enable to allow the timeline to be created:
sudo systemctl enable --now snapper-timeline.timer
A second systemd timer unit handles the cleanup of stale snapshots so that your snapshots remain manageable. You should enable this unit as well, for example:
sudo systemctl enable --now snapper-cleanup.timer
When the systemd timer units are enabled, periodic snapshot
events trigger automatically for every snapper configuration
that has the TIMELINE_CREATE
variable
enabled. If you wish to disable periodic snapshots for a
particular configuration, change the variable value to
no
in the configuration file.
By default, the snapper timeline configuration keeps 10 hourly,
10 daily, 10 monthly, and 10 yearly snapshots. Snapshots are
pruned by the cleanup timer. For busy subvolumes such as the
root
subvolume, you might want to modify
these values to better cater to your requirements. You set these
values by changing the following configuration variables:
TIMELINE_LIMIT_HOURLY="10" TIMELINE_LIMIT_DAILY="10" TIMELINE_LIMIT_WEEKLY="10" TIMELINE_LIMIT_MONTHLY="10" TIMELINE_LIMIT_YEARLY="10"
The cleanup timer also prunes other snapshots to keep the total
number of snapshots reduced. See the
SNAPPER(8)
and
SNAPPER-CONFIGS(5)
manual pages for more
information.
You can install the DNF snapper plugin on a system to automatically trigger pre and post snapshots for DNF transactions. This feature can help you roll back changes in cases where system package upgrades cause a failure that you need to debug or to enable you to analyze which files were modified during an installation or upgrade. Note that this plugin requires no user configuration or interaction to work. To install the plugin, use the following command:
sudo dnf install python3-dnf-plugin-snapper
When installed, a snapshot is triggered for each subsequent DNF transaction. See https://dnf-plugins-extras.readthedocs.io/en/latest/snapper.html for more information.
Working With Btrfs Snapshots by Using Snapper
To list the snapshots that exist for a snapper configuration or subvolume, run:
sudo snapper -c config_name list
To display the files and directories that have been added, removed, or modified between two snapshots, use the status subcommand and specify the numbers of the two snapshots that you want to compare:
sudo snapper -c config_name status N .. N'
To display the differences between the contents of all the files in between two snapshots, use the diff subcommand:
sudo snapper -c config_name diff N .. N'
You can also display the difference in a single file over two snapshots by providing the full path to the file:
sudo snapper -c config_name diff N .. N' /path/to/file
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'
Note that undoing a change does not revert the file system to the previous snapshot but it reverts modifications made to existing files in the snapshot. This means that files created after the snapshot was taken continue to remain after an undochange operation. The undochange subcommand does not check data integrity for its changes. You should be careful of using this command without clearly evaluating the implications of the changes that it is likely to make.
For more information, see the snapper(8)
manual page.
You can mount any snapshot generated by snapper just as you would work with any other Btrfs snapshot. You may need to correlate the snapshot volume id with the snapper snapshot number to work out which snapshot you should mount or restore. Run the snapper list command to identify the number of the snapshot you wish to roll back to. For example, to see all pre and post snapshots, to roll back to a snapshot from before a DNF package update was run:
sudo snapper -c root list -t pre-post
Running the previous command produces the following output:
Pre # | Post # | Pre Date | Post Date | Description | Userdata ------+--------+------------------------------+------------------------------+---------------------------------+--------- 4 | 5 | Wed 25 Nov 2020 09:07:21 EST | Wed 25 Nov 2020 09:07:25 EST | /usr/bin/dnf install vim | 127 | 128 | Mon 30 Nov 2020 08:25:42 EST | Mon 30 Nov 2020 08:30:57 EST | /usr/bin/dnf update |
Note that the number of the pre snapshot that we intend to mount is 127 in this case. Use the btrfs subvolume list command to obtain the subvolume ID for the snapper snapshot and use this or the path to the snapshot subvolume to mount the file system, for example:
sudo btrfs subvolume list /|grep .snapshots.*127
The output of the previous command is as follows:
ID 521 gen 11533 top level 268 path .snapshots/127/snapshot
Then, run the following command:
sudo mount -o subvolid=521 /dev/sda2 /mnt
You can also use this information to boot into a snapshot of the root file system. See Mounting Alternate Snapshots as the root File System for more infomration.
Working With a Btrfs root File System
Important:
In Oracle Linux 9, the Btrfs file system and all the features that are documented in this chapter are supported in the Unbreakable Enterprise Kernel (UEK) release only. Working with Btrfs file system features requires that you boot the system by using UEK R7.
You can create a Btrfs root file system during an installation. To do so, you must boot the system by using UEK R7.
To find out the ID of the parent of the root file system subvolume, use the following command:
sudo btrfs subvolume list /
Note in the output of the previous command that the top level ID is set with an ID of 5. The top level of the file system is effectively the root of the file system and can be used to access all the subvolumes within the file system:
ID 256 gen 1591 top level 5 path boot ID 258 gen 1591 top level 5 path root ID 259 gen 1514 top level 5 path home ID 262 gen 1514 top level 258 path var/lib/portables"
In the previous example, the installation root
file system subvolume has an
ID of 258. The subvolume with ID 258 (root
) is mounted as /
.
The default subvolume (root
) with ID 258 is mounted as the active root file
system.
The mount command shows the device that's mounted as the
root
file system and indicates the subvolume ID (258):
sudo mount|grep 'on / '
/dev/sda2 on / type btrfs (rw,relatime,seclabel,space_cache,subvolid=258,subvol=/root)
Note that the top-level file system in the previous output isn't mounted by default. To mount the top-level file system volume, use the following commands:
sudo mkdir /mnt sudo mount -o subvolid=5 /dev/sda2 /mnt
If you list the contents of /mnt
, you can view
each of the subvolumes within the file system volume, including
the root
subvolume, for example:
ls /mnt
Running the previous command displays the following output:
boot home root
Note that the contents of /
and /mnt/root
are identical,
as s shown in the following example where a file (foo
) that's created in
/mnt/root
is also visible in /
:
sudo touch /mnt/root/foo ls /
Running the previous command displays the following output:
bin boot dev etc foo home instroot lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Now, list the contents of /mnt/root
:
sudo ls /mnt/root
bin boot dev etc foo home instroot lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Remove the /foo
directory, then list the
contents of /
:
sudo rm -f /foo sudo ls /
bin boot dev etc home instroot lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
List the contents of /mnt/root
again:
sudo ls /mnt/root
bin boot dev etc home instroot lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Creating Snapshots of the root File System
To take a snapshot of the current root
file
system:
-
Mount the top level of the root file system on a suitable mount point.
sudo mount -o subvolid=5 /dev/sda2 /mnt
-
Change directories to the mount point, then take the snapshot. In the following example, the
install
subvolume is currently mounted as theroot
file system:sudo cd /mnt sudo mkdir -p /mnt/snapshots sudo btrfs subvolume snapshot root snapshots/root_snapshot_1
-
Change directories to
/
and unmount the top level of the file system.sudo cd / sudo umount /mnt
The list of subvolumes now includes the newly created snapshot.
sudo btrfs subvolume list /
ID 256 gen 1332 top level 5 path boot ID 258 gen 1349 top level 5 path root ID 259 gen 1309 top level 5 path home ID 261 gen 1309 top level 258 path var/lib/portables ID 264 gen 1348 top level 5 path snapshots/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:
sudo btrfs subvolume set-default 264 /
To ensure that the GRUB command line does not overwrite your settings, make the following update:
current_grub_kernel=$(sudo grubby --default-kernel); sudo grubby --remove-args="rootflags=subvol=root" --update-kernel $current_grub_kernel
Reboot the system for the changes to take effect.
Check that the snapshot subvolume ID and subvolume is mounted as the root filesystem:
sudo mount|grep 'on / '
/dev/sda2 on / type btrfs (rw,relatime,seclabel,space_cache,subvolid=264,subvol=/snapshots/root-snapshot1)
Deleting Snapshots of the root File System
Note:
A snapshot cannot be deleted if it is set as the default ID for a subvolume. Deleting a snapshot while it is in use as the root file system may cause system failure and requires a hard physical reset. Before deleting a snapshot that is set as the default subvolume for the root File System, change the default ID and reboot the system, for example:
sudo btrfs subvolume set-default 258 / reboot
To delete a snapshot, do the following:
-
Mount the top level of the file system, for example:
sudo mount -o subvolid=5 /dev/sda2 /mnt
-
Change directories to the mount point and delete the snapshot.
$ sudo cd /mnt sudo btrfs subvolume delete snapshots/root-snapshot1
-
Change directories to
/
and unmount the top level of the file system.sudo cd / sudo umount /mnt
The list of subvolumes now does not include
snapshots/root-snapshot1
.sudo btrfs subvolume list /
ID 256 gen 1332 top level 5 path boot ID 258 gen 1349 top level 5 path root ID 259 gen 1309 top level 5 path home ID 261 gen 1309 top level 258 path var/lib/portables