Btrfs Snapshots and Subvolumes: Using Copy on Write Filesystems in Practice
AI generated
$
/etc
Linux
Btrfs Snapshots and Subvolumes
Using copy on write filesystems in practice

Anyone who only knows the ext4 versus XFS comparison misses the real payoff of Btrfs: subvolumes as independently managed file trees, and snapshots that appear in milliseconds thanks to copy on write. Used correctly, this becomes a safety net before every risky deployment, without a separate backup tool.

11 min read Linux Btrfs Storage

1. Why copy on write changes volume management

Classic filesystems such as ext4 overwrite data blocks in place when saving, which makes snapshots technically expensive and usually requires an extra layer such as LVM. Btrfs takes a different approach: every change to a block is written as a new copy, while the old block stays around as long as something still references it. This exact principle is what makes snapshots on Btrfs cheap enough to create before every single package update or deployment without a second thought.

Subvolumes are not a replacement for partitions, but independent, named file trees inside a single Btrfs filesystem that can be mounted, snapshotted, and deleted independently of each other. A typical server layout creates separate subvolumes for root, for home, and for database directories, so that a snapshot of root never accidentally freezes terabytes of application data that already have their own backup strategy in place.

2. Creating and understanding subvolumes

A new subvolume is created with a single command and then behaves like a regular directory, while internally being managed as its own B tree with its own tree ID. This independence is why a subvolume can be mounted, unmounted, or set as the default subvolume for the whole filesystem mount on its own, something many distributions rely on for the root subvolume.

One important practical point: a subvolume shares the available free space with every other subvolume on the same filesystem, so there is no fixed size allocation like with a classic partition, unless quotas are configured. That simplifies planning considerably, because space does not need to be split up front and instead gets consumed dynamically wherever it is actually needed.


# Create a new subvolume for the MySQL data directory
btrfs subvolume create /mnt/data/mysql

# List all subvolumes on the filesystem
btrfs subvolume list /mnt/data

# Show details for a single subvolume, including UUID and parent reference
btrfs subvolume show /mnt/data/mysql

3. Creating snapshots: read only versus read write

A snapshot is technically nothing more than another subvolume whose file tree exactly matches the source subvolume at the moment it was taken, without a single data block being copied. Only once a file changes in either the original or the snapshot does copy on write kick in and write the changed block anew, while the old block remains visible unchanged in the other subvolume.

For rollback purposes, read only snapshots are the right choice, because they guarantee the frozen state cannot accidentally be modified, while read write snapshots make sense when work should continue directly inside the snapshot, for example to test a configuration change without touching the original.


# Create a read only snapshot of the root subvolume
btrfs subvolume snapshot -r / /.snapshots/root-2026-08-08

# Create a read write snapshot for experimental changes
btrfs subvolume snapshot / /.snapshots/root-testing

# Check whether a subvolume is read only
btrfs property get /.snapshots/root-2026-08-08 ro

4. Practical case: rollback before risky deployments

Before every larger Magento deployment, kernel update, or package upgrade, a read only snapshot of the affected subvolume is a worthwhile final safeguard. If the deployment fails or the server behaves unexpectedly afterward, the previous state can be restored without an elaborate restore procedure, because the snapshot already sits fully on disk instead of needing to be unpacked from a backup archive.

The actual rollback works by renaming or deleting the current subvolume and putting the snapshot in its place as a writable subvolume instead. For a root subvolume referenced by the bootloader, a single entry in the bootloader configuration pointing at the snapshot subvolume ID is often enough, so a reboot alone loads the previous state again.


# Move the current, broken subvolume out of the way
mv /mnt/data/mysql /mnt/data/mysql-broken

# Put the snapshot in its place as a writable subvolume
btrfs subvolume snapshot /.snapshots/mysql-pre-deploy /mnt/data/mysql

# Remove the broken subvolume permanently once verified
btrfs subvolume delete /mnt/data/mysql-broken

5. Essential btrfs commands for everyday use

Besides creating and deleting subvolumes, a handful of other commands belong in every Btrfs administrator's standard toolkit. The call btrfs filesystem show gives an overview of every device involved in a filesystem, while btrfs filesystem usage provides a far more detailed breakdown of used, free, and allocated space than the classic df ever could.

A deleted subvolume does not disappear immediately, but is first marked as orphaned and then removed in the background by the kernel's cleaner thread, which can take several minutes for very large snapshots and should be accounted for in scripts that immediately rely on freed up disk space afterward.


# Show devices and sizes for a Btrfs filesystem
btrfs filesystem show /mnt/data

# Detailed disk space breakdown, including allocation
btrfs filesystem usage /mnt/data

# Check for pending background deletion of subvolumes
btrfs subvolume sync /mnt/data

6. Disk space and CoW: what a snapshot really costs

Right after creation, a snapshot costs practically no additional disk space, since it fully shares every data block with the original. Actual consumption only grows over time, proportional to the amount of blocks changed in either the original or the snapshot since it was taken, which is why a snapshot on a heavily write intensive database directory binds space far faster than one on a fairly static configuration directory.

The classic du command is unsuitable for judging this overhead, because it counts every file individually without accounting for the fact that many blocks are shared across several subvolumes. A look at the qgroup statistics is far more reliable, separating exclusively held disk space per subvolume from shared disk space and giving a much more realistic picture of how much space a deletion would actually free up.


# Enable quota groups to see exclusive vs. shared disk space
btrfs quota enable /mnt/data

# Show exclusively held and shared disk space per subvolume
btrfs qgroup show -pcre /mnt/data

7. Automating snapshots instead of maintaining them by hand

Manually created snapshots before a deployment make sense, but they are no substitute for a regular snapshot strategy during day to day operation. Tools such as snapper take over both the scheduled creation and, more importantly, the cleanup of old snapshots according to configurable retention rules, so the number of hourly, daily, and weekly snapshots does not grow unchecked and eat up available disk space.

Anyone who wants to avoid extra tooling can achieve a comparable effect with a simple cron job and a script that deletes older snapshots by timestamp right after creating a new one. In both cases, cleanup must run just as reliably as creation, since an unbounded number of snapshots noticeably slows down operations such as btrfs balance.


#!/usr/bin/env bash
# scripts/btrfs-snapshot-rotate.sh: create daily snapshot, drop old ones
set -euo pipefail

TS=$(date +%Y-%m-%d)
btrfs subvolume snapshot -r /mnt/data/mysql /.snapshots/mysql-$TS

# Remove snapshots older than 7 days
find /.snapshots -maxdepth 1 -name 'mysql-*' -mtime +7 \
  -exec btrfs subvolume delete {} \;

8. Best practices for a sensible subvolume layout

A well thought out layout separates areas that genuinely benefit from snapshots from areas that should deliberately be excluded. The root subvolume, configuration directories, and application code classically belong in the snapshotted area, while log directories and temporary data are often kept as separate subvolumes without regular snapshots, since they change constantly and would needlessly increase snapshot overhead.

Database directories deserve special attention: MySQL and similar systems write many small, scattered changes, which leads to fragmentation on a copy on write filesystem. For such directories, the nodatacow attribute is worth setting, disabling copy on write for individual files or directories and noticeably reducing fragmentation, at the cost of checksumming and snapshot efficiency for exactly that area.

9. Common pitfalls in production use

The most important principle first: a snapshot is not a backup as long as it sits on the same physical storage device. A disk failure destroys the original and every snapshot alike, which is why snapshots should always be understood as a complement to a real offsite backup, never as a replacement for one.

Another pitfall involves nodatacow combined with snapshots: once a snapshot of a file with that attribute exists, the very next write still triggers copy on write exactly once, since the snapshot would otherwise become inconsistent. Anyone using nodatacow for database files should set the attribute before the first write ever happens, ideally right when the directory is created, rather than applying it retroactively to database files that are already populated.

Command Purpose Typical use Note
btrfs subvolume snapshot -r Create a read only snapshot Rollback safeguard before deployment No data block gets copied
btrfs subvolume snapshot Create a read write snapshot Experimental changes without touching the original Changes stay local to the snapshot
btrfs qgroup show Analyze disk space per subvolume Clarify how much space a deletion would free Requires quotas enabled beforehand
btrfs subvolume delete Remove a subvolume or snapshot Cleanup after a successful rollback Deletion runs asynchronously in the background
btrfs property set ro Toggle write protection Make a snapshot writable again afterward Handle rollback relevant snapshots with care

Mironsoft

Server administration, Docker hosts, and performance tuning

Linux servers nobody on the team really understands anymore?

We handle setup, hardening, and performance tuning of Linux servers and Docker hosts for Magento deployments, documented and traceable instead of grown and unclear.

Server Audit

Review the existing server configuration for security gaps and performance bottlenecks.

Docker Host Setup

Set up and secure production-ready Docker environments for Magento cleanly.

Monitoring & Tuning

Measure resource usage and tune systemd, kernel, and services with purpose.

10. Summary

Btrfs Snapshots

Core concept

Copy on write allows snapshots without data copying in milliseconds

Practical value

Read only snapshot before every risky deployment as rollback safeguard

Disk space

Grows only with actual changes, analyzed via qgroups rather than du

Most important rule

A snapshot never replaces an offsite backup on separate storage

11. FAQ: Btrfs Snapshots

1What is the difference between a subvolume and a classic partition?
A subvolume is an independent file tree inside a single Btrfs filesystem that dynamically shares available disk space with other subvolumes. A partition, by contrast, has a fixed size and its own filesystem, which makes later resizing considerably more involved.
2How much disk space does a freshly created snapshot use?
Practically none, since a new snapshot initially shares every data block with the original. Only as changes are made to either the original or the snapshot does the exclusively held disk space grow, visible through the qgroup statistics.
3Can I make a read only snapshot writable afterward?
Yes, btrfs property set can remove the ro property, turning the snapshot into a regular, writable subvolume. For rollback purposes, this conversion should only happen right before the actual rollback.
4Does a Btrfs snapshot replace a classic backup?
No, a snapshot only protects against logical failures such as a broken deployment, not against hardware failure, since it lives on the same physical storage device. A complete backup strategy with an external storage location is still required.
5Why is MySQL often run with nodatacow?
Databases write many small, scattered changes, which leads to heavy fragmentation on a copy on write filesystem. The nodatacow attribute disables copy on write for the affected directory and reduces fragmentation, at the cost of checksumming and snapshot efficiency.
6How long does deleting a large snapshot take?
The actual removal runs asynchronously through a kernel cleaner thread and can take several minutes for very large snapshots. btrfs subvolume sync can be used to wait specifically until all pending deletions have finished.
7What happens to nodatacow files once a snapshot exists?
The next write after the snapshot was taken still triggers copy on write exactly once, so the snapshot stays consistent. After that, nodatacow behavior applies again for further changes, until the next snapshot is created.
8Which tool is suited for automating snapshots?
Snapper is the most common solution and handles both scheduled creation and cleanup of old snapshots according to configurable rules. Alternatively, a cron job with a short rotation script is enough for simple cases.
9Why does du report incorrect values for subvolume sizes?
The du command counts every file individually and does not account for the fact that many blocks are shared across multiple subvolumes. The btrfs qgroup statistics separate exclusively held from shared disk space and give a more realistic picture.
10How should I plan a subvolume layout for a Magento server?
Root subvolume, application code, and configuration belong in the regularly snapshotted area, while log directories and temporary data should be kept as separate subvolumes without a snapshot obligation. The database directory deserves its own subvolume with the nodatacow attribute.