"$@"
}
+# warn on command fail
+w() {
+ local ret
+ ret=0
+ "$@" || ret=$?
+ if (( ret != 0 )); then
+ d "WARNING: exit code $ret of: $*" >&2
+ return $ret
+ fi
+}
+
# mkdir + mount from fstab.
mnt() {
local dir
fi
}
-# Input vars: $vol, PWD=$root_dir (from get-btrfs-root-mountpoint)
+# Input vars: $vol, $root_dir (from get-btrfs-root-mountpoint)
+# Note: we cd $root_dir.
expire-leaf-vols() {
local leaf_vols count leaf_limit_time leaf_new_limit_time leaf
+ cd $root_dir
leaf_vols=($vol.leaf.*)
count=${#leaf_vols[@]}
leaf_limit_time=$(( EPOCHSECONDS - 60*60*24*60 )) # 60 days
# This goes backwards from oldest. leaf_new_limit_time is to avoid
# deleting very recent leafs.
for leaf in ${leaf_vols[@]}; do
- leaf_time=$(date -d ${leaf#$vol.leaf.} +%s)
+ leaf_time=$(date -d ${leaf#"$vol".leaf.} +%s)
if (( leaf_limit_time > leaf_time || ( leaf_new_limit_time > leaf_time && count > 30 ) )); then
- b btrfs sub del $leaf
+ w b btrfs sub del $leaf || return 0
fi
count=$((count-1))
done
#
# Input vars: $root_dir (from get-btrfs-root-mountpoint)
dedupe-btrbk() {
- local parentid subvol parent_sub i lines
+ local parentid subvol parent_sub i lines tmpstr
local -a bsubs
subvol="$1"
parentid=$(btrfs sub show $subvol | awk '$1 == "Parent" && $2 == "UUID:" {print $3}')
# in testing, same subvol is 136 bytes. allow some overhead. 32 happens sometimes under systemd.
# $ errno 32
# EPIPE 32 Broken pipe
- lines=$(btrfs send --no-data -p $parent_sub $subvol | btrfs receive --dump | head -n 100 | wc -l || [[ $? == 141 || ${PIPESTATUS[0]} == 32 ]])
- if [[ $lines == 0 ]]; then
+ warnret=0
+ tmpstr=$(btrfs send --no-data -p $parent_sub $subvol | btrfs receive --dump | head -n 100 || [[ $? == 141 || ${PIPESTATUS[0]} == 32 ]]) || warnret=$?
+ if (( warnret != 0 )); then
+ d "WARNING: dedupe-btrbk: btrfs-send returned:$warnret, giving up on deduping leaf subvol"
+ return 0
+ fi
+ mapfile -t lines <<<"$tmpstr"
+ if [[ ${#lines[@]} == 2 && ${lines[0]} == "At subvol"* && ${lines[1]} == snapshot* ]]; then
# example output of no differences:
# snapshot ./qrtest uuid=c41ff6b7-0527-f34d-95ac-190eecf54ff5 transid=2239 parent_uuid=64949e1b-4a3e-3945-9a8e-cd7b7c15d7d6 parent_transid=2239
- echo suspected identical: $parent_sub $subvol
- b btrfs sub del $subvol
+ echo identical: $parent_sub $subvol
+ w b btrfs sub del $subvol || return 0
fi
}
#
# Note: we cd $root_dir.
mv-vol-to-leaf() {
- local leaf
+ local leaf date
cd $root_dir
# no leaf volumes for qd
if [[ $vol == qd ]]; then
- b btrfs sub del qd
+ w b btrfs sub del qd || return 0
return 0
fi
- dedupe-btrbk $root_dir/$vol
-
- leaf=$vol.leaf.$(date +%Y-%m-%dT%H:%M:%S%z)
+ date=$(date +%Y-%m-%dT%H:%M:%S%z)
+ leaf=$vol.leaf.$date
b mv $vol $leaf
- b btrfs property set -ts $leaf ro true
+ w b btrfs property set -ts $leaf ro true ||:
+ w dedupe-btrbk $root_dir/$leaf || return 0
}
# Input vars: $vol
# got remounted with a different filesystem.
#
# Input vars: ${pruned_vols[@]}
-bind-mismatch-fix() {
- local vol d_id b b_id found_mismatch
+#
+# Set leftover vars: $root_dir
+mount-mismatch-fix() {
+ local vol vol_id mp mp_id found_mismatch
local -a to_umount
for vol in ${pruned_vols[@]}; do
set-d-binds
+ get-btrfs-root-mountpoint
found_mismatch=false
- d_id=$(stat -c%d $d)
- for b in ${binds[@]}; do
- if mountpoint -q $b; then
- b_id=$(stat -c%d $b)
- if [[ $d_id != "$b_id" ]]; then
- found_mismatch=false
- to_umount+=($b)
+ vol_id=$(stat -c%d $root_dir/$vol)
+ for mp in $d ${binds[@]}; do
+ if mountpoint -q $mp; then
+ # %d = "device number", which is different between
+ # %subvols. TODO: probably change this to UUID. Try to find out
+ # %if device id is unique on this host or what.
+ mp_id=$(stat -c%d $mp)
+ if [[ $vol_id != "$mp_id" ]]; then
+ found_mismatch=true
+ to_umount+=($mp)
fi
fi
done
if $found_mismatch; then
- d "WARNING: fixing bind mount(s): ${to_umount[*]}, pointing to old subvol."
+ d "WARNING: fixing mount(s):${to_umount[*]}, pointing to old subvol."
umount-kill ${to_umount[@]}
m mnt ${to_umount[@]}
fi
umount_vols+=($vol)
for dir in ${binds[@]} $d; do
if mountpoint -q $dir; then
- to_umount=($dir)
+ to_umount+=($dir)
fi
done
else
if ! kill-dir TERM TERM TERM INT INT HUP HUP TERM TERM TERM INT INT HUP HUP; then
if $force; then kill-dir KILL; fi
fi
- if ! b btrfs sub del $dir; then
- echo "$0: ERROR: failed to delete subvolume $dir" >&2
- ret=1
- fi
+ w b btrfs sub del $dir || return 0
fi
b btrfs sub snapshot $fresh_snap $dir
if $umount_ret; then
fresh_snap=$(cat /nocow/btrfs-stale/$vol 2>/dev/null)
get-btrfs-root-mountpoint
- cd $root_dir
mv-vol-to-leaf
expire-leaf-vols
b btrfs sub snapshot $fresh_snap $vol
ret=0
mkdir -p /var/log/btrbk
-setup-root2
setup-fstab
prune-vols
-bind-mismatch-fix
+w mount-mismatch-fix ||:
plan-umounts
if (( ${#umount_vols[@]} >= 1 )); then
umount-then-mount-latest
fi
-amy-root2-latest
+
+# i don't want to be stuck trying to fix these if they fail for some reason
+w setup-root2 ||:
+w amy-root2-latest ||:
if (( ret >= 1 )); then
echo "$0: exit status $ret. see error(s) above" >&2