Inspect, Snapshot and Scrub a Btrfs Filesystem

Btrfs punishes guessing more than most filesystems, so this is a small, repeatable maintenance workflow rather than a set of one-off commands. It covers identifying the installed tool, inspecting devices and space, listing subvolumes, taking a read-only snapshot, and checking scrub status. The examples use btrfs-progs 6.6.3, the version on the reference machine.

Allow 20 to 30 minutes for the commands themselves, plus however long a scrub takes on your storage. You need a shell, btrfs-progs, and a mounted Btrfs filesystem. Substitute your real mount point for /mnt/btrfs. Read-only inspection normally needs no elevated privilege; snapshot creation, deletion and scrub require suitable filesystem permissions and commonly need sudo.

Safety boundary: do not experiment against a production device path. A snapshot protects against accidental changes, but it is not an independent backup: it shares extents with its source and does not protect against loss of the filesystem or its devices.

1. Confirm the installed command

Start with the version and top-level syntax. These only read local program metadata:

$ btrfs --version
btrfs-progs v6.6.3
$ btrfs --help
usage: btrfs [global] <group> [<group>...] <command> [<args>]

The command is organised as a group followed by a command, such as btrfs filesystem show or btrfs subvolume list. The installed tool accepts shortened names when they are unambiguous, but use full names in scripts: this stops a future command becoming ambiguous after an upgrade.

Checkpoint: the version is recorded, and your scripts use complete command names.

2. Find the filesystem and inspect its devices

Confirm the path is actually on Btrfs before running maintenance:

$ findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS /mnt/btrfs
/mnt/btrfs /dev/mapper/data btrfs rw,relatime,ssd,space_cache=v2
$ btrfs filesystem show /mnt/btrfs
Label: 'data'  uuid: 11111111-2222-3333-4444-555555555555
        Total devices 1 FS bytes used 12.34GiB
        devid    1 size 100.00GiB used 20.00GiB path /dev/mapper/data

The UUID, label, sizes and device path above are examples; your output will differ. If findmnt reports another filesystem type, stop here. If it reports no mount, use the correct mounted path rather than passing a directory from a different filesystem.

btrfs filesystem show accepts a path, UUID, label or device, and shows every Btrfs filesystem it can find with no argument. It exits zero on success; check that status explicitly in a script:

$ btrfs filesystem show /mnt/btrfs >/tmp/btrfs-show.txt
$ printf 'show status: %s\n' "$?"
show status: 0

The temporary file is optional and safe to remove once you have read it. Do not treat a label alone as a unique identity if your environment permits duplicate or stale device metadata.

3. Read allocation and subvolume state

Use filesystem usage for the overall view, then list the subvolumes. Both are ordinary read-only queries:

$ btrfs filesystem usage /mnt/btrfs
Overall:
    Device size:                 100.00GiB
    Device allocated:             20.00GiB
    Device unallocated:           80.00GiB
    Device missing:                0.00B
    Used:                          12.34GiB
$ btrfs subvolume list /mnt/btrfs
ID 256 gen 42 top level 5 path root
ID 257 gen 41 top level 5 path home

Numbers and rows are host-specific. Btrfs allocation profiles mean a simple free-space figure is not the whole story, especially on multi-device or redundant layouts. If the output says detailed chunk information could not be read, rerun the usage query with appropriate privileges and record the warning rather than guessing what the numbers mean.

For a script or a ticket, save the output together with the filesystem UUID and command version: a useful before-and-after record that changes nothing.

Checkpoint: you know the mounted path, the participating devices, the allocation summary and the subvolume names. Choose the exact source subvolume before continuing.

4. Create a read-only snapshot

A snapshot is a new subvolume containing the source's initial state. Create it beside the source, with a name that includes the purpose and date:

$ sudo btrfs subvolume snapshot -r /mnt/btrfs/home /mnt/btrfs/.snapshots/home-before-change
Create a readonly snapshot of '/mnt/btrfs/home' in '/mnt/btrfs/.snapshots/home-before-change'

The destination parent must exist and be on the same Btrfs filesystem. -r makes the snapshot read-only, a useful guard against accidentally editing the captured state. It does not make the snapshot independent storage, and it does not stop later deletion by an administrator.

Verify both the snapshot and its read-only property:

$ btrfs subvolume list /mnt/btrfs | grep -F '.snapshots/home-before-change'
ID 300 gen 45 top level 5 path .snapshots/home-before-change
$ btrfs property get -t subvol /mnt/btrfs/.snapshots/home-before-change ro
ro=true

If the destination already exists, stop and choose another name. Do not remove an existing snapshot merely to make a command repeatable: confirm its owner, retention policy and backup status first.

5. Remove a snapshot only after checking it

Destructive action: deleting a subvolume removes its directory immediately and queues its data blocks for later cleanup. It is not an undo operation. Confirm the exact path and that another backup or snapshot still holds anything you need:

$ btrfs subvolume show /mnt/btrfs/.snapshots/home-before-change
$ sudo btrfs subvolume delete --commit-after /mnt/btrfs/.snapshots/home-before-change
Delete subvolume ...

--commit-after waits for a transaction commit at the end of the delete. It does not turn the deletion into a recoverable archive. To wait for the reclamation to finish before measuring usage, use subvolume sync:

$ sudo btrfs subvolume sync /mnt/btrfs
$ btrfs filesystem usage /mnt/btrfs

There is no general restore command for a deleted snapshot. Recovery depends on other snapshots, send streams or backups, which is why retention automation should delete by an explicit, reviewed policy rather than a broad wildcard.

6. Scrub the filesystem deliberately

A scrub reads filesystem data and metadata and checks Btrfs checksums. It is maintenance, not a replacement for btrfs check. A normal scrub can use substantial device bandwidth and may repair a bad copy when redundant replicas exist, so schedule it for a quiet period:

$ sudo btrfs scrub start -B /mnt/btrfs
scrub done for ...
        scrub started at ...
        scrub duration: ...
        data_extents_scrubbed: ...
        read_errors:             0
        csum_errors:              0
        corrected_errors:         0
        uncorrectable_errors:     0

-B keeps the command in the foreground so the shell receives the result. Without it the scrub can run in the background; check it later:

$ sudo btrfs scrub status /mnt/btrfs
scrub status for ...
        scrub started at ...
        scrub status: finished
        read_errors: 0
        csum_errors: 0
        corrected_errors: 0
        uncorrectable_errors: 0

The local command also offers -r for read-only scrub. Do not read that as a guarantee of zero writes when the filesystem is mounted read-write: current upstream documentation warns implementation details can still cause some writes. If zero writes are a hard requirement, use a genuinely read-only mount and an appropriate maintenance plan.

Non-zero read, checksum or uncorrectable error counts need investigation. Preserve the status output, check device health and verify your backups before jumping to repair commands.

7. Keep repair and balance behind a separate decision

Warning: btrfs check is for an unmounted device and defaults to read-only. Never aim it at a mounted production filesystem. Its --repair mode is explicitly dangerous and should only follow analysis by someone who understands the reported corruption:

$ sudo btrfs check --readonly /dev/mapper/data
Opening filesystem to check...
Checking all filesystems...

Use the device identified in step 2, not a guessed partition. If the filesystem is mounted, unmount it according to your service's maintenance procedure first. A check does not repair ordinary checksum errors, and a repair attempt can make recovery harder.

Likewise, do not run an unfiltered balance as a routine space command. btrfs balance start /mnt/btrfs can move data and metadata across the whole mounted filesystem, consume significant IO and require free workspace. Inspect usage and use a narrowly justified filter, or leave balance to a documented storage plan. You can monitor or stop an existing operation with btrfs balance status, pause and cancel.

Mount options that affect the workflow

The companion btrfs(5) manual describes filesystem-wide mount behaviour. Options are processed in order, and the last occurrence wins. The applied options are visible through findmnt or mount, so inspect those instead of assuming an /etc/fstab line took effect. Many options apply to the whole filesystem and the first mounted subvolume, not independently to every subvolume.

Be especially cautious with options that change copy-on-write, checksums or compression. The manual documents interactions such as nodatacow and compress: a mount option is not a harmless per-directory preference. Test a planned change on a disposable filesystem, record the previous mount line, and keep a maintenance-window rollback that restores it before rebooting.

Done means