X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=btrfsmaint;h=33cae4a36280351c170155f11fc83ba8ca3b2102;hb=ea108a03dfa2d7f73447c0b14210d766e5ee5d9b;hp=6c7dbb1f6788119cafa9cac1dc2cae559cd2c07b;hpb=b18dade73dedfe69aa741f8417947d83c4208f2d;p=distro-setup diff --git a/btrfsmaint b/btrfsmaint index 6c7dbb1..33cae4a 100755 --- a/btrfsmaint +++ b/btrfsmaint @@ -15,7 +15,12 @@ source /a/bin/errhandle/err dusage="5 10" musage="5" -e() { echo "cron: $*"; "$@"; } +e() { + echo "cron: $*" + if ! $dryrun; then + "$@" + fi +} check-idle() { type -p xprintidle &>/dev/null || return 0 @@ -36,13 +41,12 @@ check-idle() { fi } - usage() { cat <&2 usage 1 @@ -76,27 +84,53 @@ main() { idle=true if ! $force; then check-idle + if ! $check; then + min=0 + max_min=300 + # When the cron kicks in, we may not be idle (physically sleeping) yet, so + # wait. + while ! $idle && (( min < max_min )); do + min=$(( min + 1 )) + sleep 60 + check-idle + done + # If we've waited a really long time for idle, just give up. + if (( min == max_min )); then + return + fi + fi fi - tmp=$(mktemp) + tmp=$(mktemp) fnd="findmnt --types btrfs --noheading" for x in $($fnd --output "SOURCE" --nofsroot | sort -u); do mnt=$($fnd --output "TARGET" --first-only --source $x) [[ $mnt ]] || continue - if ! btrfs dev stats -c $mnt >$tmp; then - if diff -q $mnt/btrfs-dev-stats $tmp; then - diff -u $mnt/btrfs-dev-stats $tmp | mail -s "$HOSTNAME: error: btrfs dev stats -c $mnt" root@localhost - cat $tmp >$mnt/btrfs-dev-stats + #### begin look for diff in stats, eg: increasing error count #### + + # Only run for $check, since it runs in parallel to non-check, avoid + # race condition. + if $check; then + if ! btrfs dev stats -c $mnt >$tmp; then + if diff -q $mnt/btrfs-dev-stats $tmp; then + diff -u $mnt/btrfs-dev-stats $tmp | mail -s "$HOSTNAME: error: btrfs dev stats -c $mnt" root@localhost + cat $tmp >$mnt/btrfs-dev-stats + fi fi + rm -f $tmp fi + #### end look for diff in stats, eg: increasing error count #### - if ! $idle; then - btrfs scrub cancel $mnt &>/dev/null ||: - continue - fi if $check; then + if ! $idle; then + if $dryrun; then + echo "$0: not idle. if this wasnt a dry run, btrfs scrub cancel $mnt" + else + btrfs scrub cancel $mnt &>/dev/null ||: + fi + fi continue fi @@ -118,25 +152,42 @@ main() { e ionice -c 3 btrfs balance start -musage=$usage $mnt done fi - # e btrfs filesystem df $mnt - # e df -H $mnt - date=$( - btrfs scrub status $mnt | \ - sed -rn 's/^\s*scrub started at (.*) and finished.*/\1/p' - ) + date= + scrub_status=$(btrfs scrub status $mnt) + if printf "%s\n" "$scrub_status" | grep -i '^status:[[:space:]]*finished$' &>/dev/null; then + date=$(printf "%s\n" "$scrub_status" | sed -rn 's/^Scrub started:[[:space:]]*(.*)/\1/p') + fi + if [[ ! $date ]]; then + # output from older versions, at least btrfs v4.15.1 + date=$( + printf "%s\n" "$scrub_status" | \ + sed -rn 's/^\s*scrub started at (.*) and finished.*/\1/p' + ) + fi if [[ $date ]]; then + if $dryrun; then + echo "$0: last scrub finish for $mnt: $date" + fi date=$(date --date="$date" +%s) - # if date is sooner than 90 days ago + # if date is sooner than 60 days ago # the wiki recommends 30 days or so, but - # it makes the comp lag like shit for a day, - # so I'm going with 90 days. - if (( date > $(date +%s) - 60*60*24*30 )); then - echo "cron: skiping scrub of $mnt" + # I'm going with 60 days. + if (( date > EPOCHSECONDS - 60*60*24*60 )); then + if $dryrun; then + echo "$0: skiping scrub of $mnt, last was $(( (EPOCHSECONDS - date) / 60/60/24 )) days ago, < 30 days" + fi continue fi fi # -c 2 -n 4 is from btrfsmaintenance, does ionice e btrfs scrub start -Bd -c 2 -n 4 $mnt + + # We normally only do one disk since this is meant to be run while I sleep + # and if we try to do all disks, we invariably end up doing a scrub still + # after I've woken up. So, just do one per day. + if ! $force; then + return 0 + fi done }