Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions auto-rules-io/usr/bin/big-btrfs-balance
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,45 @@ FolderRoot=$(btrfs device stats / | tail -n1 | cut -f1 -d] | cut -f2 -d[)

FolderHome=$(btrfs device stats /home | tail -n1 | cut -f1 -d] | cut -f2 -d[)

# A usage filter also picks the last, partly filled chunk that the previous
# balance just packed, so a filesystem that changed little since then has the
# same data rewritten on every boot and frees nothing. Freeing a chunk needs
# at least a chunk of allocated-but-unused space. With single, DUP or RAID1
# profiles, data chunks are at most 1 GiB, and the kernel reports the
# metadata chunk size, which is at least 256 MiB (its data chunk size there
# is only the upper limit). On smaller filesystems both are 10% of the size,
# rounded up to 16 MiB.
balance() {
local type slack size tenth data_chunk=1073741824 meta_chunk filters=()
meta_chunk=$(cat "/sys/fs/btrfs/$(findmnt -no UUID "$1")/allocation/metadata/chunk_size" 2>/dev/null)
meta_chunk=${meta_chunk:-268435456}
size=$(btrfs filesystem usage -b "$1" 2>/dev/null | awk '/Device size:/ {print $3; exit}')
if (( size )); then
tenth=$(( (size / 10 + 16777215) / 16777216 * 16777216 ))
(( tenth < data_chunk )) && data_chunk=$tenth
(( tenth < meta_chunk )) && meta_chunk=$tenth
fi
while read -r type slack; do
case $type in
Data) (( slack >= data_chunk )) && filters+=(-dusage=50) ;;
Metadata) (( slack >= meta_chunk )) && filters+=(-musage=50) ;;
Data+Metadata) filters+=(-dusage=50 -musage=50) ;;
esac
done < <(btrfs filesystem df -b "$1" | awk -F'[ ,=]+' '$1 == "Data" || $1 == "Metadata" || $1 == "Data+Metadata" {
for (i = 2; i < NF; i++) { if ($i == "total") t[$1] += $(i+1); if ($i == "used") u[$1] += $(i+1) }
} END { for (k in t) print k, t[k] - u[k] }')

if (( ${#filters[@]} )); then
nice -n+20 ionice -c 3 btrfs balance start "${filters[@]}" "$1"
fi
}

if [ "$FolderRoot" != "" ]; then
nice -n+20 ionice -c 3 btrfs balance start -dusage=50 -musage=50 /
balance /
fi

if [ "$FolderHome" != "" ] && [ "$FolderHome" != "$FolderRoot" ]; then
nice -n+20 ionice -c 3 btrfs balance start -dusage=50 -musage=50 /home
balance /home
fi