Create, Snapshot and Delete Subvolumes with btrfs subvolume
Btrfs subvolumes look like directories but behave like separate filesystems, and btrfs subvolume is how you manage them. This guide takes you from inspecting a filesystem to creating a subvolume, snapshotting it read-only, and deleting a disposable one. The examples match btrfs-progs 6.6.3, installed here as package version 6.6.3-1.1build2.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 15 minutes. You need a mounted Btrfs filesystem and an account allowed to administer it. Substitute an existing mount point for /mnt/btrfs. Commands that change filesystem state are shown with sudo; inspect commands may work without it, depending on permissions.
1. Confirm the filesystem and current subvolumes
Check that the path is really on Btrfs, then list its subvolumes:
$ findmnt -no FSTYPE,OPTIONS /mnt/btrfs
$ sudo btrfs subvolume list -p -u /mnt/btrfs
The first command should begin with btrfs. The second prints an ID, generation, parent information and a path, with UUID fields because of -u. The path shown by list is relative to the filesystem top level, not necessarily to the directory you supplied.
Checkpoint
You have recorded the ID and path of anything you might later change. The top-level subvolume has ID 5 and cannot be removed.
Tip
Do not assume a directory is an ordinary directory. A subvolume looks like one, but it is a separate Btrfs hierarchy.
2. Create a working subvolume
Create a new subvolume below the mount point. The destination has to be inside the Btrfs filesystem:
$ sudo btrfs subvolume create /mnt/btrfs/work
On success, btrfs reports the created subvolume. The new directory is usable immediately, but its persistent numeric ID is assigned by Btrfs and is not the directory name. Verify both the path and its metadata:
$ sudo btrfs subvolume show /mnt/btrfs/work
$ sudo btrfs subvolume list /mnt/btrfs
show includes the subvolume ID, UUID, parent ID, creation generation and flags. A normal new subvolume is read-write.
Tip
Subvolumes share the filesystem's storage pool unless you configure quotas. Creating another one does not reserve a fixed block device or capacity.
3. Make a read-only snapshot
A snapshot starts with the source subvolume's content and initially shares extents through copy-on-write. Make a read-only one when you need a stable tree for inspection or later send/receive work:
$ sudo btrfs subvolume snapshot -r /mnt/btrfs/work /mnt/btrfs/work-before-change
$ sudo btrfs subvolume show /mnt/btrfs/work-before-change
The -r matters: without it, the snapshot is read-write. Check that Flags shows it as read-only. You can still mount a read-write subvolume read-only, but that mount choice does not change the subvolume's own read-only property.
Now prove it. Write test data only to /mnt/btrfs/work, then compare with the snapshot:
$ sudo sh -c 'printf "%s\n" changed > /mnt/btrfs/work/example.txt'
$ test ! -e /mnt/btrfs/work-before-change/example.txt && echo "snapshot is unchanged"
snapshot is unchanged
Warning
This is a local rollback or comparison point, not a backup. The source and snapshot initially share data blocks, so disk damage or an accident affecting the filesystem can hit both. Keep an independent backup for recovery.
4. Inspect the default subvolume before changing it
Every Btrfs filesystem has a default subvolume, used when it is mounted without an explicit subvol or subvolid. Find it before you touch boot or mount behaviour:
$ sudo btrfs subvolume get-default /mnt/btrfs
Changing the default is an operational decision, not a cosmetic rename. It hides the top-level view on the next mount. If you have deliberately chosen a subvolume ID, the form is:
$ sudo btrfs subvolume set-default SUBVOLUME_ID /mnt/btrfs
$ sudo btrfs subvolume get-default /mnt/btrfs
Replace SUBVOLUME_ID with an ID from list or show.
Warning
Do not run this example against a production filesystem until you have checked how its mount units, /etc/fstab entries and recovery procedure refer to the old default.
Recovery
To undo the change, run set-default again with the previously recorded ID.
5. Remove only a confirmed disposable subvolume
Deletion is destructive. First inspect the exact path and its contents, and check that it is not the default subvolume or a source currently in use by send:
$ sudo btrfs subvolume show /mnt/btrfs/work-before-change
$ sudo find /mnt/btrfs/work-before-change -maxdepth 2 -print
When the path is definitely disposable, delete it and ask for a transaction commit before the command returns:
$ sudo btrfs subvolume delete --commit-after /mnt/btrfs/work-before-change
Delete subvolume ...
$ sudo btrfs subvolume list /mnt/btrfs
The directory disappears promptly, but Btrfs removes the data blocks in the background. --commit-after waits for the transaction to be committed; it does not make the deletion reversible.
Warning
There is no ordinary undo command. Restore the subvolume from an independent backup, or recreate it from another snapshot if one exists.
To wait for the deletion work itself to finish, use:
$ sudo btrfs subvolume sync /mnt/btrfs
With no ID, sync waits for the deletion requests known when it starts. It can take a while for a large or heavily shared subvolume.
Tip
The default owner cannot normally delete a subvolume unless the filesystem was mounted with user_subvol_rm_allowed. Using sudo avoids that permission failure but does not bypass the safety checks for a default or active send subvolume.
Common traps
- Snapshots are not recursive. Nested subvolumes form a barrier: a snapshot contains a stub for the nested subvolume, not its files. Plan nested layouts explicitly.
- Quick deletion is not reclaimed space. Deletion returning quickly does not mean all space is back. Check with
btrfs subvolume syncwhen cleanup completion matters. - Read-only can be lost. Changing a read-only snapshot to read-write can break incremental send assumptions. Preserve read-only snapshots used as send bases.
- Mount paths hide the hierarchy. A path can be visible through a mount of one subvolume while its parent hierarchy is hidden. Use
btrfs subvolume listand IDs rather than guessing from mount paths.
Done means
- Filesystem confirmed. The path is on Btrfs and you recorded the relevant subvolume IDs.
- Creation verified. You checked the new subvolume with
showandlist. - Snapshot understood. You confirmed its read-only state and did not treat it as an independent backup.
- Default recorded. You noted the old default before any
set-defaultchange. - Deletion done carefully. You inspected the target, used
--commit-after, and ransyncwhen cleanup completion mattered.