BTRFS at first glance seems to be the panacea as far as file systems are concerned, but there are several aspects to consider before putting it into production. First, we will understand the way information is stored in this file system. We will show how to check available space and how to rebalance blocks to optimize available space.
We will start by explaining what ROW is and its consequences. We will continue with the differences with COW, how to check available space, and how to rebalance data.
ROW:
- When writing to a file, new data is written to another location, not to the original file, and the blocks of the original file are marked as free.
- If a snapshot is generated or a file is copied with cp –reflink=always, the blocks of the snapshot are those of the original file except for the changes that are made, which are written to a separate location.
If the first case occurs frequently, the file system will end up with a very high internal fragmentation , leaving us with no usable space despite having space available.
In some cases (especially databases), it is useful to disable ROW. This can be done in two different ways, at the partition level by indicating it in the fstab or at the directory level using chattr:
nodatacow
Using chattr:
NOTE: If snapshots have been taken, copies have been made using --reflink=always
, or the files already existed, disabling ROW with chattr will not work. The old files can be moved, ROW can be disabled, and the data can be dumped again.
Actually, BTRFS is not COW, it is ROW:
Some people insist that Btrfs does “Redirect-on-write” rather than “Copy-on-write”
https://storageswiss.com/2016/04/01/snapshot-101-copy-on-write-vs-redirect-on-write/
The difference between ROW and COW is how the old version of a modified block is stored.
-
COW
- W: The original block is copied to another location and the data is updated, which involves one read and two writes: 1R/2W.
- R from a snapshot: The original blocks are read until a modified one is found, then the copy made when writing is searched and read.
-
ROW
- W: The original blocks are left intact, and when a block is modified, it is written to a different location: pointer generation.
- R from a snapshot: References to modified blocks are saved as pointers, which must be read.
ROW requires 1/3 of the I/O operations that COW requires when modifying a block and 0 computational overhead when reading snapshots.
With COW, performance degrades as snapshots are created. COW is usually used to take snapshots with a very limited lifespan (usually for backups), while ROW snapshots are usually kept for much longer.
Disk space:
To show the disk space used, the basic df
command is not useful. Instead, use:
The only useful data is:
Device size: 1.45TiB
Used: 38.83GiB
Free (estimated): 1.41TiB (min: 1.06TiB)
In free-min
, it is due to internally consumed data and internal fragmentation of the FS.
The complete output of the command is something like this:
btrfs fi usage /
Overall:
Device size: 1.45TiB
Device allocated: 768.04GiB
Device unallocated: 720.84GiB
Device missing: 0.00B
Used: 38.83GiB
Free (estimated): 1.41TiB (min: 1.06TiB)
Data ratio: 1.00
Metadata ratio: 1.99
Global reserve: 48.00MiB (used: 0.00B)
Rebalancing:
Defragmentation requires disk space. BTRFS organizes disk space into blocks, which are of a certain size. If a file occupies four and a half blocks and is taking up five, another file may occupy X and a half blocks, and the halves of the two files can be grouped into a single block. Whether or not to move the data from one block to another is decided based on the space occupied in that block. For example, in this case, if 5% or less of the block is used, it is relocated.
NOTE: If the file system is composed of more than one disk, the balancer will also distribute the files among them to make access faster.