BTRFS maintenance on SSD

I wrote the following script to perform the recommended maintenance on Tumbleweed with btrfs running on a SSD. This is for a couple new installs so I don’t have much history of running it.

I decided to go for the manual route since I can follow what’s going on. It runs in about 25 sec here, so not much of a problem, at least until the drive goes way past the current 6% usage. Running once a fortnight seems a good schedule, and I can review everything in a single place.

Another relevant aspect is that individual tasks won’t interfere with each other, nor with a send/receive.

Currently it handles a single btrfs file system, but I plan on supporting any additional ones.

#!/bin/bash

COLOR1='\0330;33m'
COLOR2='\0330;34m'
NC='\0330m'

printf "${COLOR1}> Disk state before maintenance${NC}

"
btrfs filesystem usage /
printf "
"

printf "${COLOR1}> Cleaning old snapshots${NC}

"
/usr/lib/snapper/systemd-helper --cleanup
printf "
"

printf "${COLOR1}> Checking data integrity${NC}

"
btrfs scrub start -BR /
printf "
"

printf "${COLOR1}> Compacting data blocks${NC}

"
btrfs balance start --verbose -dusage=5 /
printf "
"

printf "${COLOR1}> Discarding unused blocks${NC}

"
fstrim --fstab --verbose
printf "
"

printf "${COLOR1}> Disk state after maintenance${NC}

"
btrfs filesystem usage /
printf "
"

printf "${COLOR1}> S.M.A.R.T.${NC}

"
smartctl --scan | awk '{ print $1 } ' | sort | xargs -n1 -I {} sh -c 'printf "${COLOR2}>> {}${NC}

" && smartctl -a {}'
printf "
"


Hey Admin, Thanks for sharing this blog. I hope you will share more blogs like this. Keep blogging.You get here all the steps to fix 123.hp.setup issues.

Thanks for sharing the script, good to have this set of commands.

Did some code to measure how long the script takes:


START=`date +%s`

<body>

END=`date +%s`
RUNTIME=$((END-START))
printf "${COLOR1}> Script to ${RUNTIME} seconds${NC}

"

Running this script after every “zypper dup” and today it took 998 seconds.

Thanks for sharing!

Looking at your script and at this openSUSE SDB article https://en.opensuse.org/SDB:Disable_btrfsmaintenance, the switches and calls to balance as well as the scrub switch are different. Would you care to give a look and comment? Cheers.

Sure!

Balance

btrfs balance start -dusage=0 /
btrfs balance start -v -dusage=5 /
btrfs balance start -v -dusage=10 /
btrfs balance start -musage=0 /
btrfs balance start -v -musage=3 /

Remove -(d/m)usage=0, because btrfs already handles this automatically since v3.18.
Remove -musage=3, because I’ve read somewhere this shouldn’t be done (not that it would crash on you, just don’t).
Remove -dusage=10, because I’ve plenty of space atm. YMMV

Scrub

btrfs scrub start -Bd /

This is simply a matter of how I want to consume the report. I have a single device, so no need for -d, and I want to see the result as soon as it’s done, otherwise a call to btrfs scrub status is necessary, so the -R.

On another note, I saw linux 5.6 brings the mount option discard=async, which is awesome and that’s when I’m gonna remove the fstrim call from the script.

Hope this helps!

Great. Thanks a lot.
Cheers, and stay healthy.

Ah, another one, please: Your script, the btrfsmaintenance github https://github.com/kdave/btrfsmaintenance/blob/master/README.md, and the Arch Wiki mention scrub first, then balance. Only the openSUSE SDB has it the other way round. Haven’t checked the btrfs Wiki yet. Is there a rationale or recommendation as to the ordering?

Scrub checks if the file system can read from disk the same data that was written to it. I think it makes more sense running it before moving data around (balance). Every time a block is read from disk, its checksum is computed and compared. I understand that’s still the case if the block is to be relocated during a balance. If there’s a bit-flip in there, I don’t know how balance will deal with that, maybe it stops, or ignore the block. I’d prefer to handle it during a scrub. Good that you mention though, because I think my script will continue with the balance even in case scrub reports a checksum mismatch.