btrfs free space. It’s complicated. Still.
Posted by jpluimers on 2018/07/09
Everytime a btrfs based volume runs out of space, I’m reminded of these:
There are a few scripts that help you assess quota usage. If you think they are wrong, then you need to btrfs quota rescan / which tells you that it started, but won’t tell when it’s finished (nor wil journalctl -xe a.k.a. journalctl --catalog --pager-end), but dmesg does:
# dmesg | grep qgroup
[ 316.608122] BTRFS info (device sda2): qgroup scan completed (inconsistency flag cleared)
For now I’ve this quick script to start investigation:
~/Versioned/btrfs-du/btrfs-du && df -h | grep "\/$\|^[^\/]" && btrfs quota rescan -s /
It assumes there is quota on the root (enable with btrfs quota enable /) and is based on my fork github.com/jpluimers/btrfs-du. The df will limit itself to the root (trailing / matched by \/$) or disks not mounted from / (matched by ^[^\/]).
–jeroen
References (not solutions):
- [WayBack] Snapper, The ultimate Snapshot Tool for Linux: Cleanup based on Disk Usage
- [WayBack] Quota support – btrfs Wiki
- [WayBack] Tool for understanding each snapshot used space size · Issue #51 · openSUSE/snapper
- From my own blog:
- How can a partition be full if du does not show it is? (via: linux – Super User) #OpenSuSE #btrfs #snapshots
- A bash script to btrfs snapshot details like disk sizes (requires btrfs quota to be enabled)
- Nice diskinfo alias showing du, df, btrfs, parted, lsblk
- how to resize (grow) device partition of a multi-device BTRFS filesystem?
- Interesting thread about various file systems: BTRFS, ReiserFS, ext4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python2 | |
| import argparse | |
| import subprocess | |
| parser = argparse.ArgumentParser( | |
| description='Gives quotas from a BTRFS filesystem in a readable form' | |
| ) | |
| parser.add_argument( | |
| '–unit', metavar='U', type=str, | |
| default='G', | |
| help='SI Unit, [B]ytes, K, M, G, T, P', | |
| ) | |
| parser.add_argument( | |
| 'mount_point', metavar='PATH', type=str, | |
| default='/', | |
| help='BTRFS mount point', | |
| ) | |
| sys_args = parser.parse_args() | |
| mount_point = sys_args.mount_point | |
| multiplicator_lookup = ['B', 'K', 'M', 'G', 'T', 'P'] | |
| subvolume_data = dict() | |
| cmd = ["btrfs", "subvolume", "list", mount_point] | |
| for line in subprocess.check_output(cmd).splitlines(): | |
| args = line.strip().split(' ') | |
| subvolume_data[int(args[1])] = args[-1] | |
| print("subvol\t\t\t\t\t\tgroup total unshared") | |
| print("-" * 79) | |
| cmd = ["btrfs", "qgroup", "show", "–raw", mount_point] | |
| for line in subprocess.check_output(cmd).splitlines(): | |
| args = [x for x in line.strip().split(' ') if len(x)>0] | |
| try: | |
| subvolume_id = args[0].split('/')[-1] | |
| subvolume_name = subvolume_data[int(subvolume_id)] | |
| except: | |
| subvolume_name = "(unknown)" | |
| multiplicator = 1024 ** multiplicator_lookup.index(sys_args.unit) | |
| try: | |
| try: | |
| total = "%02.2f" % (float(args[1]) / multiplicator) | |
| unshared = "%02.2f" % (float(args[2]) / multiplicator) | |
| except ValueError: | |
| continue | |
| print("%s\t%s\t%s%s %s%s" % ( | |
| subvolume_name.ljust(40), | |
| args[0], | |
| total.rjust(10), sys_args.unit, | |
| unshared.rjust(10), sys_args.unit, | |
| )) | |
| except IndexError: | |
| pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import argparse | |
| import subprocess | |
| parser = argparse.ArgumentParser( | |
| description='Gives quotas from a BTRFS filesystem in a readable form' | |
| ) | |
| parser.add_argument( | |
| '–unit', metavar='U', type=str, | |
| default='G', | |
| help='SI Unit, [B]ytes, K, M, G, T, P', | |
| ) | |
| parser.add_argument( | |
| 'mount_point', metavar='PATH', type=str, | |
| default='/', | |
| help='BTRFS mount point', | |
| ) | |
| sys_args = parser.parse_args() | |
| mount_point = sys_args.mount_point | |
| multiplicator_lookup = ['B', 'K', 'M', 'G', 'T', 'P'] | |
| subvolume_data = dict() | |
| cmd = ["btrfs", "subvolume", "list", mount_point] | |
| for line in subprocess.check_output(cmd).splitlines(): | |
| args = str(line, encoding='utf8').split() | |
| subvolume_data[int(args[1])] = args[-1] | |
| print("subvol\t\t\t\t\t\tgroup total unshared") | |
| print("-" * 79) | |
| cmd = ["btrfs", "qgroup", "show", "–raw", mount_point] | |
| for line in subprocess.check_output(cmd).splitlines(): | |
| args = str(line, encoding='utf8').split() | |
| try: | |
| subvolume_id = args[0].split('/')[-1] | |
| subvolume_name = subvolume_data[int(subvolume_id)] | |
| except: | |
| subvolume_name = "(unknown)" | |
| multiplicator = 1024 ** multiplicator_lookup.index(sys_args.unit) | |
| try: | |
| try: | |
| total = "%02.2f" % (float(args[1]) / multiplicator) | |
| unshared = "%02.2f" % (float(args[2]) / multiplicator) | |
| except ValueError: | |
| continue | |
| print("%s\t%s\t%s%s %s%s" % ( | |
| subvolume_name.ljust(40), | |
| args[0], | |
| total.rjust(10), sys_args.unit, | |
| unshared.rjust(10), sys_args.unit, | |
| )) | |
| except IndexError: | |
| pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| [[ ! -d $1 ]] && { echo Please pass mountpoint as first argument >&2 ; | |
| exit 1 ; } | |
| while read x i x g x x l x p | |
| do | |
| volName[i]=$p | |
| done < <(btrfs subvolume list $1) | |
| while read g r e | |
| do | |
| [[ -z $name ]] && echo -e "subvol\tqgroup\ttotal\tunshared" | |
| group=${g##*/} | |
| [[ ! -z ${volName[group]} ]] && name=${volName[group]} || name='(unknown)' | |
| echo $name $g `numfmt –to=iec $r` `numfmt –to=iec $e` | |
| done < <(btrfs qgroup show –raw $1 | tail -n+3) | column -t |






Leave a comment