Skip to content

Instantly share code, notes, and snippets.

@qiwichupa
Created May 7, 2025 15:22
Show Gist options
  • Save qiwichupa/dec7827f2aff11ebc545c942d9425afb to your computer and use it in GitHub Desktop.
Save qiwichupa/dec7827f2aff11ebc545c942d9425afb to your computer and use it in GitHub Desktop.
samba network folder sizing for folders on btrfs-raid
#!/usr/bin/env python3
# based on omv-btrfs-dfree from openmediavault
import os
import re
import subprocess
import sys
from systemd import journal
CUSTOMRATIO = 0 # set ratio of your btrfs volume if samba user is not root (smb.conf: force user = root)
LOGGING = 0 # 0 - off, 1 - on. journalctl -t 'SMBUS'
def main():
path = os.path.realpath(sys.argv[1] if len(sys.argv) > 0 else '.')
output = subprocess.run(
['btrfs', 'filesystem', 'usage', '--raw', '-T', path],
capture_output=True
).stdout.decode()
re_matches_for_total = r'.+Device size:\s+(\d+)\n.+'
matches_for_total = re.match(
re_matches_for_total,
output, re.DOTALL
)
if os.getuid() == 0: # if samba user is root we can get ratio to calculate total space
re_matches_for_ratio = r'.+Data ratio:\s+(\d+\.\d+).+'
matches_for_ratio = re.match(
re_matches_for_ratio,
output, re.DOTALL
)
ratio = float(matches_for_ratio.group(1))
else: # else set ratio = 1 but can get wrong total size
if CUSTOMRATIO == 0:
ratio = 1
else:
ratio = CUSTOMRATIO
if os.getuid() == 0: # if user is root we can get estimated (minimum) free space
re_matches_for_available = r'.+Free \(estimated\):\s+\d+\s+\(min: (\d+)\)\n.+'
else: # otherwise only 'statfs' free
re_matches_for_available = r'.+Free \(statfs, df\):\s+(\d+)\n.+'
matches_for_available = re.match(
re_matches_for_available,
output, re.DOTALL
)
if matches_for_total is not None:
totalb = matches_for_total.group(1)
availableb = matches_for_available.group(1)
if LOGGING == 1:
journal.stream('SMBUS').write(f'SMB VARS: userid={os.getuid()}, ratio={ratio}, availableb={availableb}, totalb={totalb}')
for line in output.splitlines():
journal.stream('SMBUS').write(f'{line}')
total = round(int(totalb) // (1024 * ratio))
available = round(int(availableb) // 1024)
else:
output = subprocess.run(
['df', '--portability', '--print-type', '--block-size=1K', path],
capture_output=True
).stdout.decode()
_, _, total, _, available, *_ = output.split('\n')[1].split()
sys.stdout.write(f'{total} {available} 1024\n')
if __name__ == "__main__":
sys.exit(main())
[Public]
....
dfree command = /etc/samba/btrfs-dfree.py
dfree cache time = 60
# optionally. Otherwise set btrfs volume ratio manually via CUSTOMRATIO variable in python script
force user = root
force group = root
....
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment