The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,860 other subscribers

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):


#!/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


#!/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

view raw

btrfsQuota.3.py

hosted with ❤ by GitHub


#!/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

view raw

btrfsQuota.sh

hosted with ❤ by GitHub

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.