Set and Inspect Btrfs Qgroup Limits Safely
You will build a Btrfs qgroup hierarchy and put a limit on the parent group, then check the accounting actually reflects it. The examples use btrfs-progs 6.6.3-1.1build2, installed on the reference system. Qgroups are quota accounting objects: they do not resize a filesystem or create free space.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about twenty minutes, plus time for a quota rescan on a large filesystem. You need a mounted Btrfs filesystem, the btrfs command, and root privileges for quota changes. Replace /mnt/my-vault with a mounted filesystem you administer. Do not run the examples against a production mount until you have checked the identifiers and chosen a maintenance window.
Checkpoint
This guide changes quota metadata. The commands that enable quota, create groups, assign relationships and set limits require elevated privileges. The inspection commands may also need them, depending on how the filesystem is mounted and your local permissions.
1. Confirm the filesystem and command version
Start with read-only checks. The path must be inside the Btrfs filesystem whose quotas you intend to manage:
$ findmnt -T /mnt/my-vault -t btrfs
$ btrfs --version
btrfs-progs v6.6.3
If findmnt reports another filesystem type, stop. Qgroup commands apply to Btrfs, and a plausible-looking path is not enough. If your installed version differs, check its local help before copying an option from another host.
2. Enable quota accounting
Qgroups depend on Btrfs quota support. Enable it once for the filesystem:
$ sudo btrfs quota enable /mnt/my-vault
The command normally prints nothing on success. Confirm that qgroup accounting is available by listing the automatically created level-0 groups:
$ sudo btrfs qgroup show --human-readable /mnt/my-vault
qgroupid rfer excl
-------- ---- ----
0/5 16.00KiB 16.00KiB
The exact rows and sizes depend on the filesystem. Level 0 groups have the form 0/<subvolume id> and are associated with subvolumes. Enabling quota is persistent filesystem state, so undo it only when you have confirmed that no service or monitoring process relies on these limits:
$ sudo btrfs quota disable /mnt/my-vault
Warning
Disabling quota removes the quota accounting that this guide creates. It is a filesystem-wide change, not a temporary pause. Do not use it as a quick fix for a single bad qgroup.
3. Identify the child qgroups
For a parent limit to cover two subvolumes, first find their numeric IDs. This is an ordinary read-only query:
$ sudo btrfs subvolume list /mnt/my-vault
ID 261 gen 61 top level 5 path a
ID 262 gen 62 top level 5 path b
In this example the child qgroups are 0/261 and 0/262. Do not substitute directory names for these IDs. Snapshotting and deleting subvolumes can make a remembered ID wrong for a later operation, so re-run the listing when returning to this task.
Checkpoint
Write down the actual mount path, subvolume IDs and intended parent ID before running the next commands. A qgroup identifier uses level/id; level 0 is reserved for subvolume groups, while a higher level is suitable for an administrative parent.
4. Create and populate a parent qgroup
Create a level-1 parent, then assign the two level-0 children to it. The example parent ID 1/100 is arbitrary; choose an unused identifier in your own naming scheme:
$ sudo btrfs qgroup create 1/100 /mnt/my-vault
$ sudo btrfs qgroup assign 0/261 1/100 /mnt/my-vault
$ sudo btrfs qgroup assign 0/262 1/100 /mnt/my-vault
Assignment creates the hierarchy. It does not move blocks or merge the subvolumes. On this btrfs-progs release, assignment schedules a rescan automatically when the relationship could make existing accounting inconsistent. That rescan may take time and can add load to a busy filesystem.
Inspect parent and child relationships explicitly:
$ sudo btrfs qgroup show --sync -p -c --human-readable /mnt/my-vault
qgroupid rfer excl max_rfer max_excl
-------- ---- ---- -------- --------
0/261 16.00KiB 16.00KiB
0/262 16.00KiB 16.00KiB
1/100 32.00KiB 32.00KiB
Your output can include other qgroups and the columns vary with the options supported by the installed command. The useful checks are that 1/100 exists, both child IDs are present, and the parent reports their accounted usage after synchronisation.
5. Apply the right kind of limit
Set a referenced-data limit on the parent with a size such as 10M:
$ sudo btrfs qgroup limit 10M 1/100 /mnt/my-vault
The -c form is the default in this release and limits the amount of data after compression. It is currently not possible to turn that behaviour off. Use -e when you instead need to limit space exclusively assigned to the qgroup:
$ sudo btrfs qgroup limit -e 8M 1/100 /mnt/my-vault
These are different measurements. A fresh snapshot shares most blocks with its source, so referenced data can be high while exclusive data is low. Choose the measurement that matches the resource you are protecting. Setting a limit does not retroactively delete data, and writes can fail once the relevant limit is reached.
Verify the stored limits in raw bytes when a script needs an unambiguous value:
$ sudo btrfs qgroup show --sync --raw -r -e /mnt/my-vault
qgroupid rfer excl max_rfer max_excl
-------- ---- ---- -------- --------
1/100 33554432 33554432 10485760 8388608
The numbers above are illustrative: use the output from your host as the source of truth. Human-readable output is base 1024 by default; --si selects base 1000 for size display. Keep one format in monitoring so a change of display options is not mistaken for a quota change.
6. Handle a rescan or inconsistent accounting
A qgroup relationship changes which groups own or reference extents. When a full rescan is needed, ask Btrfs to rebuild the numbers:
$ sudo btrfs quota rescan /mnt/my-vault
$ sudo btrfs quota rescan -s /mnt/my-vault
Do not run both commands as a routine pair. The first starts a rescan; -s is the status form and reports the current state. On a large filesystem the operation may still be running, so use the status command again and then repeat btrfs qgroup show --sync before judging the result.
If you deliberately repeat many assignments and want to suppress automatic rescans, the qgroup command supports --no-rescan. That leaves accounting potentially inconsistent until you run a deliberate rescan. Prefer the default --rescan unless you have measured the cost and have a controlled maintenance procedure.
7. Undo one relationship or the whole example
To remove one child from the parent, reverse the relationship:
$ sudo btrfs qgroup remove 0/262 1/100 /mnt/my-vault
Removing a relationship does not delete either qgroup or change the subvolume. When the relationship is gone and the parent is no longer needed, remove its limit and destroy the parent:
$ sudo btrfs qgroup limit none 1/100 /mnt/my-vault
$ sudo btrfs qgroup destroy 1/100 /mnt/my-vault
Warning
Destruction is irreversible at the qgroup level. A parent or child group that still has relationships cannot be destroyed. Check with btrfs qgroup show -p -c first, and remove only relationships you recognise.
If subvolumes were deleted without their level-0 qgroups being cleaned up, clear stale level-0 groups with:
$ sudo btrfs qgroup clear-stale /mnt/my-vault
This does not remove higher-level administrative qgroups. It also does not restore a destroyed subvolume qgroup. If a level-0 group was destroyed while its subvolume still exists, recreate 0/<subvolume id> before expecting quota for that subvolume to work again.
Done means
- Filesystem confirmed.
findmntconfirmed the target is the intended Btrfs filesystem. - Quota enabled. It was turned on deliberately, and the automatic level-0 qgroups are visible.
- Hierarchy verified. The parent qgroup contains the child IDs you checked from
btrfs subvolume list. - Limit applied. The chosen referenced or exclusive limit appears in a synchronised qgroup report.
- Rescan status known. You know whether one is running and what maintenance window it needs.
- Removal tested. You have a tested removal sequence for any relationship or parent group you created.