BTRFS (B-tree File System) is a modern copy-on-write filesystem for Linux with integrated volume management, snapshots, checksumming, and multi-device support.
Table of Contents#
- Overview
- Filesystem Management
- Subvolumes
- Snapshots
- Device Management
- RAID Configuration
- Scrub and Data Integrity
- Compression
- Quota Groups (qgroups)
- Mount Options
- Special Use Cases
- Troubleshooting
- See Also
- Sources
1. Overview#
BTRFS is a copy-on-write (CoW) filesystem that integrates volume management features directly into the filesystem layer. It was designed to address the scaling and reliability needs of modern Linux storage.
Key features:
- Copy-on-Write (CoW) - data is never overwritten in place; new data is written to a new location, then metadata is atomically updated
- Built-in checksumming - CRC32C (default), xxhash, sha256, or blake2b for both data and metadata
- Snapshots - instant, space-efficient snapshots via CoW
- Subvolumes - lightweight logical divisions within a filesystem
- Integrated multi-device - RAID 0, 1, 10, 5 (unstable), 6 (unstable), and single profiles
- Online resize - grow and shrink while mounted
- Transparent compression - zstd, lzo, or zlib
- Send/receive - incremental replication between BTRFS filesystems
Kernel Version Dependencies#
Several BTRFS features depend on the kernel version:
| Feature | Minimum Kernel | Notes |
|---|---|---|
discard=async | 6.2 | Enabled by default since 6.2 |
space_cache=v2 | 4.5 | Default since 4.12 |
| RAID 5/6 | 3.19 | Still considered unstable; not recommended for production |
| zstd compression | 4.14 | Recommended compression algorithm |
| Send/receive v2 | 6.0 | Supports large files, encoded inline extents |
| Block group tree | 6.1 | Faster mount times for large filesystems |
2. Filesystem Management#
Creating a Filesystem#
# Single device
mkfs.btrfs -L <label> /dev/<device>
# Multiple devices (RAID 1 for data, RAID 1 for metadata)
mkfs.btrfs -L <label> -d raid1 -m raid1 /dev/sda /dev/sdbMounting#
mount /dev/<device> /mnt
# With specific subvolume
mount -o subvol=@ /dev/<device> /mntResizing#
# Grow to fill available space
btrfs filesystem resize max /mnt
# Grow by a specific amount
btrfs filesystem resize +10G /mnt
# Shrink by a specific amount
btrfs filesystem resize -5G /mnt
# Shrink to a specific size
btrfs filesystem resize 50G /mntChecking Usage#
# Detailed usage breakdown (data, metadata, system)
btrfs filesystem usage /mnt
# Per-device usage
btrfs filesystem show /mnt
# Disk free with allocation detail
btrfs filesystem df /mntProperties#
# Set compression on a directory
btrfs property set /path compression zstd
# Make a subvolume read-only
btrfs property set /path ro true
# Disable CoW for a directory (must be set before files are created)
chattr +C /path/to/directory3. Subvolumes#
Subvolumes are independent POSIX filesystem trees within a BTRFS filesystem. They share the same pool of storage but can be independently snapshotted, mounted, and configured.
Creating Subvolumes#
# Create subvolumes
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@log
btrfs subvolume create /mnt/@snapshotsListing Subvolumes#
btrfs subvolume list /mnt
btrfs subvolume list -t /mnt # table format with gen, top levelMounting Specific Subvolumes#
# Via fstab
/dev/sda / btrfs subvol=@,compress=zstd,noatime 0 0
/dev/sda /home btrfs subvol=@home,compress=zstd,noatime 0 0
/dev/sda /var/log btrfs subvol=@log,compress=zstd,noatime 0 0Deleting Subvolumes#
btrfs subvolume delete /mnt/@oldDefault Subvolume#
# Set the default subvolume (mounted when no subvol= option is given)
btrfs subvolume set-default <subvol-id> /mnt4. Snapshots#
Snapshots are instant copies of subvolumes. They are created in constant time regardless of the amount of data, thanks to CoW.
Creating Snapshots#
# Writable snapshot
btrfs subvolume snapshot /mnt/@ /mnt/@snapshots/@-$(date +%Y%m%d)
# Read-only snapshot (required for send/receive)
btrfs subvolume snapshot -r /mnt/@ /mnt/@snapshots/@-$(date +%Y%m%d)Restoring from a Snapshot#
# Rename the current subvolume
mv /mnt/@ /mnt/@broken
# Create a writable snapshot from the backup
btrfs subvolume snapshot /mnt/@snapshots/@-20260301 /mnt/@
# Reboot or remountSend/Receive (Incremental Replication)#
# Full send of a read-only snapshot
btrfs send /mnt/@snapshots/@-20260301 | btrfs receive /backup/
# Incremental send (only changes since the parent snapshot)
btrfs send -p /mnt/@snapshots/@-20260301 /mnt/@snapshots/@-20260302 | \
btrfs receive /backup/Deleting Old Snapshots#
btrfs subvolume delete /mnt/@snapshots/@-202602015. Device Management#
BTRFS can span multiple devices and supports online addition, removal, and replacement of devices.
Adding a Device#
# Add a new device to the filesystem
btrfs device add /dev/sdc /mnt
# Rebalance data across all devices
btrfs balance start /mntRemoving a Device#
# Remove a device (data is migrated to remaining devices)
btrfs device remove /dev/sdb /mntReplacing a Failed Device#
# Online replacement (data is copied from remaining redundant copies)
btrfs replace start <devid> /dev/new_device /mnt
# Monitor replacement progress
btrfs replace status /mntGet the device ID with:
btrfs filesystem show /mntMounting a Degraded Filesystem#
If a device is missing (failed or disconnected), mount in degraded mode:
mount -o degraded /dev/sda /mntThen replace the missing device as soon as possible.
6. RAID Configuration#
Metadata Redundancy#
By default, BTRFS stores metadata in DUP mode on single devices (two copies on the same device) and RAID1 on multi-device setups. This provides metadata protection even in non-RAID configurations.
| Profile | Copies | Min Devices | Notes |
|---|---|---|---|
single | 1 | 1 | No redundancy |
dup | 2 | 1 | Default for metadata on single device |
raid0 | 1 | 2 | Striped, no redundancy |
raid1 | 2 | 2 | Mirrored on 2 devices |
raid1c3 | 3 | 3 | Mirrored on 3 devices |
raid1c4 | 4 | 4 | Mirrored on 4 devices |
raid10 | 2 | 4 | Striped mirrors |
raid5 | 1+parity | 3 | Unstable, not recommended |
raid6 | 1+2parity | 4 | Unstable, not recommended |
Converting Between RAID Profiles#
# Convert data to RAID 1
btrfs balance start -dconvert=raid1 /mnt
# Convert metadata to RAID 1
btrfs balance start -mconvert=raid1 /mnt
# Convert both simultaneously
btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt
# Run in background
btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt --background
# Check balance status
btrfs balance status /mntVerifying RAID Profile#
btrfs filesystem usage /mntLook for the "Data" and "Metadata" profile lines in the output.
7. Scrub and Data Integrity#
Scrub reads all data and metadata from disk, verifies checksums, and repairs any corruption found using redundant copies (if available).
Running a Scrub#
# Start a scrub
btrfs scrub start /mnt
# Start a scrub in the foreground (wait for completion)
btrfs scrub start -B /mnt
# Check scrub status
btrfs scrub status /mntScheduling Regular Scrubs#
Create a systemd timer for regular scrubbing:
# /etc/systemd/system/btrfs-scrub@.timer
[Unit]
Description=Monthly BTRFS scrub on %i
[Timer]
OnCalendar=monthly
Persistent=true
RandomizedDelaySec=1w
[Install]
WantedBy=timers.target# /etc/systemd/system/btrfs-scrub@.service
[Unit]
Description=BTRFS scrub on %i
[Service]
Type=oneshot
ExecStart=/usr/bin/btrfs scrub start -B %i
IOSchedulingClass=idle
CPUSchedulingPolicy=idlesudo systemctl enable --now btrfs-scrub@mnt.timerMany distributions (e.g., openSUSE, Fedora) ship with btrfs-scrub@.timer preinstalled.
Scrub Results#
btrfs scrub status /mntKey output fields:
| Field | Meaning |
|---|---|
data_extents_scrubbed | Number of data extents verified |
csum_errors | Checksum mismatches found |
verify_errors | Metadata verification failures |
corrected_errors | Errors corrected from redundant copies |
uncorrectable_errors | Errors that could not be repaired (data loss) |
8. Compression#
BTRFS supports transparent, per-file compression.
| Algorithm | Ratio | CPU Usage | Best For |
|---|---|---|---|
zstd | Best | Moderate | General purpose (recommended) |
lzo | Low | Lowest | Real-time workloads |
zlib | Good | Highest | Maximum compression ratio |
Enabling Compression#
# At mount time
mount -o compress=zstd /dev/sda /mnt
# Per-directory
btrfs property set /mnt/data compression zstd
# Compress existing files (defragment with compression)
btrfs filesystem defragment -r -czstd /mnt/dataCompression Levels#
# zstd supports levels 1-15 (default 3)
mount -o compress=zstd:3 /dev/sda /mnt9. Quota Groups (qgroups)#
Quota groups track and limit space usage per subvolume. They are organized in a hierarchy.
Hierarchy#
Level 0: Individual subvolumes (automatically created)
0/256 = subvolume @ (root)
0/257 = subvolume @home
0/258 = subvolume @log
Level 1+: User-defined group limits
1/0 = group containing 0/256, 0/257, 0/258Each qgroup at level 0 tracks the exclusive and shared space of its subvolume. Higher-level qgroups aggregate the limits of their children.
Enabling and Using Quotas#
# Enable quotas (may cause minor performance overhead)
btrfs quota enable /mnt
# Show quota usage
btrfs qgroup show -reF /mnt
# Set a limit on a subvolume
btrfs qgroup limit 50G /mnt/@home
# Set a limit on a higher-level group
btrfs qgroup create 1/0 /mnt
btrfs qgroup assign 0/257 1/0 /mnt
btrfs qgroup limit 100G 1/0 /mnt
# Remove a limit
btrfs qgroup limit none /mnt/@home
# Disable quotas
btrfs quota disable /mntPerformance Note#
Enabling quotas adds bookkeeping overhead to every write operation. On workloads with many small writes or frequent snapshot creation, this overhead can be noticeable. Consider enabling quotas only when space enforcement is required.
10. Mount Options#
| Option | Description | Default |
|---|---|---|
compress=zstd | Transparent compression (zstd recommended) | Disabled |
compress=lzo | Transparent compression with LZO | Disabled |
compress=zlib | Transparent compression with zlib | Disabled |
nocompress | Disable compression | N/A |
discard=async | Asynchronous TRIM for SSDs | Enabled (kernel 6.2+) |
discard=sync | Synchronous TRIM for SSDs | Disabled |
nodiscard | Disable TRIM | Disabled |
noatime | Do not update access times | Disabled (recommended to enable) |
autodefrag | Automatic defragmentation | Disabled |
space_cache=v2 | Free space cache version 2 | Enabled (kernel 4.12+) |
ssd | SSD optimizations | Auto-detected |
nodatacow | Disable CoW for data (not recommended) | Disabled |
nospace_cache | Disable free space cache (degrades performance) | Disabled |
commit=<sec> | Commit interval in seconds | 30 |
degraded | Mount with missing devices | Disabled |
subvol=<path> | Mount a specific subvolume by path | Top-level |
subvolid=<id> | Mount a specific subvolume by ID | Top-level |
ro | Read-only mount | Disabled |
noacl | Disable ACLs | Disabled |
Recommended Production Mount#
/dev/sda / btrfs subvol=@,compress=zstd,noatime,space_cache=v2 0 0Important Notes#
nodatacow: Disables CoW, checksumming, and compression for affected files. Only use for specific workloads (databases, VM images).autodefrag: Helpful for random-write workloads on HDDs; may increase I/O on SSDs.noatime: Recommended for all workloads; reduces unnecessary writes.
11. Special Use Cases#
Database Performance Optimization#
Databases perform many small random writes, which conflict with BTRFS CoW behavior. Disable CoW for database data directories:
# Create a subvolume for the database
btrfs subvolume create /mnt/@database
# Set the no-CoW attribute (must be done before files are created)
chattr +C /mnt/@databaseThis disables CoW, checksumming, and compression for files in the directory.
Swap File on BTRFS#
BTRFS supports swap files starting with kernel 5.0, with restrictions:
# Create swap file (must be no-CoW, no compression, single extent)
btrfs filesystem mkswapfile --size 4G /mnt/swapfile
# Or manually (kernel < 6.1)
truncate -s 0 /mnt/swapfile
chattr +C /mnt/swapfile
fallocate -l 4G /mnt/swapfile
chmod 600 /mnt/swapfile
mkswap /mnt/swapfile
swapon /mnt/swapfileVM Images#
For virtual machine disk images, disable CoW to avoid fragmentation and write amplification:
mkdir /mnt/@vms
chattr +C /mnt/@vmsTroubleshooting#
| Issue | Cause | Solution |
|---|---|---|
No space left on device but df shows free space | Metadata space exhausted or unbalanced allocation | Run btrfs filesystem usage /mnt; if metadata is full, rebalance: btrfs balance start -musage=50 /mnt |
| Extremely slow deletes or snapshot removal | qgroups accounting overhead | Disable quotas if not needed: btrfs quota disable /mnt |
BTRFS warning: csum failed in dmesg | Data corruption detected by checksums | Run btrfs scrub start /mnt; if redundant copies exist, scrub will auto-repair |
| Mount fails after unclean shutdown | Log tree corruption | Try btrfs rescue zero-log /dev/sda; if that fails, try btrfs check --repair /dev/sda (last resort) |
| Degraded mount required | Device missing or failed | Mount with -o degraded; replace the device immediately |
| Balance never completes | Not enough free space to relocate block groups | Free space by deleting old snapshots or data; use filter flags: btrfs balance start -dusage=10 /mnt |
| RAID 5/6 data loss | Known write-hole bug in BTRFS RAID 5/6 | Do not use BTRFS RAID 5/6 for production; migrate to RAID 1 or use mdadm/ZFS for RAID 5/6 |
| High fragmentation on HDD | CoW behavior creates fragmentation over time | Enable autodefrag mount option; periodically run btrfs filesystem defragment -r /mnt |