BTRFS has an easy way to reclaim unused space per chunk that has data in the filesystem!... btrfs balance.
For official documentation on its usage go to the official docs and search for "Compact under used chunks" here: https://btrfs.readthedocs.io/en/stable/Balance.html#filter-types
The syntax is basically:
btrfs balance start -dusage=<percentageUsed/chunk> <btrfs mount path>
E.g:
btrfs balance start -dusage=10 /mnt/btrfs
The above will search all chunks in the btrfs mounted path /mnt/btrfs for any chunks that are only used up to 10%.
The data will then get relocated to other partially used chunks increasing the percentage of the chunk used to greater than 10%. Thus compacting the filesystem and more importantly releasing unused and locked away "free-space" per chunk!
In essence, defragmenting free-space
You can then put the above in a script on ever increasing percentage up to 50%. The official documentation in the link above does not recommend over 50% as it has less benefit.
e.g:
#!/usr/bin/env bash function free_chunks_up_to_50percent { local path=$1 for USAGE in {10..50..10} do echo "usage percentage= ${USAGE}" echo "path= ${path}" btrfs balance start -v -dusage=${USAGE} ${path} done } free_chunks_up_to_50percent $1
e.g: To execute the above script if it was a script-file called btrfs-reclaim-unused-space.sh for a btrfs mounted path at /mnt/btrfs to reclaim space there.
sh ./btrfs-reclaim-unused-space.sh /mnt/btrfs
For SSD's this is quite quick even on BTRFS RAIDs
For mechanical disks in BTRFS RAIDs this could take some time depending on the size of the RAID array (all types of BTRFS RAID). It is still worth running it every now and then especially if you have a lot of IO happening to the RAID. Heavy torrenting for example.