6

I cannot determine how to get the quota limit which is currently set on a btrfs subvolume. The btrfs wiki on quota doesn't seem to show this.

This is what I think I know:

  • set a quota: btrfs qgroup limit 21G /path
  • check used space: btrfs qgroup show /path

But how to check the already set limit?

lickdragon
  • 161
  • 2
  • 9

4 Answers4

5

Use options -r and -e:

btrfs qgroup show -pcre /path
uhrm
  • 66
  • 3
  • 1
    That’s useless, because it only lists abstract numbers (the “quota groups”) without any information about what quota group in linked to which subvolumes. Also it doesn’t work without enabling quotas, but enabling them, when they are too small for the current amount of data, will cause writes to fail. – Evi1M4chine Oct 17 '17 at 16:43
  • @Evi1M4chine, works fine on my system. [Pastebin](https://pastebin.com/cGbj9cNA). – Tim Aug 01 '18 at 17:54
  • @Evi1M4chine I believe you can (1) enable the quota subsystem without actually (2) imposing any quota limits. Once you do #1, you should be able to see the usage info. There is no need to ever actually impose a limit. Source: http://dustymabe.com/2013/09/22/btrfs-how-big-are-my-snapshots/ – mpb Oct 05 '22 at 17:06
5

I created a simple script that will show the quota limit for each sub-volume in the specified path and the used space too. The syntax is pretty simple:

./quota.sh path

To print the used space for all sub-volumes use the -a flag:

./quota.sh path -a

Don't forget to add execution permissions to the script.

Script:


#! /bin/sh
volumes=$(btrfs subvolume list  $1 | cut -d " " -f 9 )
snapshots=$(btrfs subvolume list -s  $1 | cut -d " " -f 14 )
regsnap=$(echo $snapshots | sed 's/ /,/g')
normalv=$(echo $volumes | sed "s/\($regsnap\)//g" )

if [ ! -z "$snapshots" ] ; then
    echo SNAPSHOTS
for p in $snapshots; do 
    quot=$(btrfs qgroup show -rF $1/$p | tail -1)
    if [ -z $2 ]; then
        (echo $quot | grep -q none) || echo $p $quot
    else
     [ "$2" == "-a" ] && echo $p $quot
    fi
done
fi

if [ ! -z "$normalv" ] ; then
    echo SUBVOLUMES
for p in $normalv; do 
    quot=$(btrfs qgroup show -rF $1/$p | tail -1)
    if [ -z $2 ]; then
        (echo $quot | grep -q none) || echo $p $quot
    else
     [ "$2" == "-a" ] && echo $p $quot
    fi
done

fi

It will print first the traditional sub-volumes and below the snapshots volumes. Sample output:

SNAPSHOTS
apple 0/258 1.32MiB 16.00KiB 20.00MiB
SUBVOLUMES
citrus/orange 0/256 1.32MiB 16.00KiB 20.00MiB
3

As we speak, btrfs is broken by design in this regard.

There is currently no function in btrfs-progs, to show which subvolume has which quota. You have to write a script (and many who fell for btrfs do), to parse the abstract quota group numbers it outputs, and list the subvolumes inside those quota groups below them. It could be added, but the btrfs developers religiously refuse to do this.

Even worse, there is not only no way to show how much of the quota a subvolume currently uses up. Which is why df only shows the total free space. It is not possible to do this at all due to how btrfs is designed at its very core. This is because subvolumes work like snapshots. Meaning, to find out how much data is in a subvolume, you’d have to scan the entire file system, and find all the files linked to that subvolume/snapshot, and add them up. Just like the du command. Which takes a lot of time. I have no idea how btrfs then knows a quota is full at all… The IRC channel could not provide me with any answer to that. (They were to busy defending their fragile over-inflated egos.) The sensible thing would be, to change the subvolume counter each time data is added or removed. Which kinda must be how btrfs knows it is full. At least I don’t know any other way. But why they would then chose to keep this available info basically a military-guarded state secret, I don’t know…

If zfs wouldn’t have such insane RAM requirements (1GB per TB … not an option on e.g. a single-board ARM computer) and the risk of data loss, due to not writing data early, due to being designed for servers with crash protection, I would recommend dumping btrfs in its favor.

Evi1M4chine
  • 161
  • 6
  • I believe the above answer by @Evi1M4chine is misleading. (1) It appears that Btrfs has a “quota” feature. Quotas are disabled by default. Enabling quotas causes Btrfs to [track the size](https://serverfault.com/questions/797219/how-to-display-quota-limit-on-btrfs-subvolume) of each subvolume. Apparently, there are (or may be) related [performance](https://btrfs.readthedocs.io/en/latest/btrfs-quota.html) and [stability](https://btrfs.readthedocs.io/en/latest/btrfs-qgroup.html) considerations. (2) ZFS only requires 1GB of RAM per TB of disk if you use data deduplication. – mpb Sep 30 '22 at 23:45
  • @mpb: Yes, officially it has a quota “feature”. But it does not let you actually show its secrets. For whatever reason. Trust me, I couldn’t believe it myself, and looked quite some time. Apparently it’s “write-only” (at creation time) or something. I would be very interested if you had found a way to actually display the quota limit, let alone how much a subvolume uses. … As it stands, btrfs seems just fundamentally misdesigned. – Evi1M4chine Oct 04 '22 at 07:28
  • Oops! I used the wrong link in my first comment. The "track the size" link should have been this: http://dustymabe.com/2013/09/22/btrfs-how-big-are-my-snapshots/ – mpb Oct 05 '22 at 16:31
  • As for showing the current quota limits, according to [the Arch wiki](https://wiki.archlinux.org/title/Btrfs#Quota): "To show usage and limits for a given path within a filesystem use `btrfs qgroup show -reF path`". I haven't actually tried this, as at present I'm mostly using ZFS. See also: [Btrfs quota known issues](https://btrfs.wiki.kernel.org/index.php/Quota_support#Known_issues). As for Btrfs being misdesignsed... imo: shared versus exclusive usage tracking + refcopy + first class snapshots = unavoidable complexity (regardless of the design). – mpb Oct 05 '22 at 17:00
0

Five years later and this is still a thing? What I used to list quotas on the filesystems under /volume1. For my needs this was static and I plan on prettyfing the data downstream so pretty minimal formatting here.

#!/bin/sh

if [ "$( id -u )" -ne 0 ]
then
    echo "ERROR: ${0}: must be run by root"
    exit 1
fi

echo "path  total   used"
for path in $( find /volume1 -maxdepth 1 -mindepth 1 -type d \! -name @\* | sort )
do
    btrfs qgroup show -pcref --raw "${path}" 2>/dev/null    \
    | sed 's#$# '"${path}"'#'
done    \
| awk 'BEGIN {OFS="\t"}
    /^[0-9]/ {print $NF,$2,$4}'

For me this prints out:

path    total   used
/volume1/prj_alpha  2529345417216   9853079650304
/volume1/prj_beta   28144091136 1099511627776
/volume1/prj_delta  2261620924416   3298534883328
/volume1/prj_epsilon    565468360704    1099511627776
/volume1/prj_gamma  37339127808 107374182400
...

I know this can be made more readable but I'm doing that in a later step, not here. For this I just needed very consistent output that is easy to parse.

keithpjolley
  • 123
  • 5