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 2,352 other followers

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

view raw
btrfsQuota.2.7.py
hosted with ❤ by GitHub

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

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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

 
%d bloggers like this: