X-Git-Url: https://iankelling.org/git/?p=distro-setup;a=blobdiff_plain;f=mount-latest-subvol;h=f9bc2def096c8710e53e812fac815216d2592ce5;hp=2ebcca04be243ec5497ce5cc330444c1ed7e9db4;hb=79b274fcd8bfa556133ab13270e84b40aebe8468;hpb=c0cc9bcf08d865418a403297d83801417e85bfb3 diff --git a/mount-latest-subvol b/mount-latest-subvol index 2ebcca0..f9bc2de 100644 --- a/mount-latest-subvol +++ b/mount-latest-subvol @@ -13,52 +13,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -# usage: mount-latest-subvol - +script=$(readlink -f -- "$BASH_SOURCE") cd / -[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@" - -errcatch() { - set -E; shopt -s extdebug - _err-trap() { - err=$? - exec >&2 - set +x - echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}:in \`$BASH_COMMAND' returned $err" - bash-trace 2 - echo "$0: exiting with code $err" - exit $err - } - trap _err-trap ERR - set -o pipefail -} -bash-trace() { - local -i argc_index=0 frame i start=${1:-1} max_indent=8 indent - local source - local extdebug=false - if [[ $(shopt -p extdebug) == *-s* ]]; then - extdebug=true - fi +[[ $EUID == 0 ]] || exec sudo -E "$script" "$@" - for ((frame=0; frame < ${#FUNCNAME[@]}-1; frame++)); do - argc=${BASH_ARGC[frame]} - argc_index+=$argc - ((frame < start)) && continue - if (( ${#BASH_SOURCE[@]} > 1 )); then - source="${BASH_SOURCE[frame+1]}:${BASH_LINENO[frame]}:" - fi - indent=$((frame-start+1)) - indent=$((indent < max_indent ? indent : max_indent)) - printf "%${indent}s↳%sin \`%s" '' "$source" "${FUNCNAME[frame]}" - if $extdebug; then - for ((i=argc_index-1; i >= argc_index-argc; i--)); do - printf " %s" "${BASH_ARGV[i]}" - done - fi - echo \' - done +source /usr/local/lib/err + +usage() { + cat </dev/null; then + if ! mountpoint -q $dir; then mkdir -p $dir - e mount $dir + m mount $dir fi } fstab() { @@ -86,7 +72,7 @@ pid-check() { for p in ${pids}; do for m in ${my_pids[@]}; do if (( p == m )); then - echo "$0: error: pids to kill includes our pid or a parent" >&2 + echo "$0: error: pids to kill includes our pid or a parent. ps output:" >&2 ps -f -p $p exit 1 fi @@ -118,17 +104,56 @@ kill-dir() { return 1 } +##### begin command line parsing ######## + +# you can remove this if you do not have options which can have args with spaces or empty. + +verbose=false force=false -if [[ $1 == -f ]]; then - force=true -fi +temp=$(getopt -l help,force,verbose hfv "$@") || usage 1 +eval set -- "$temp" +while true; do + case $1 in + -f|--force) force=true ;; + -v|--verbose) verbose=true ;; + -h|--help) usage ;; + --) shift; break ;; + *) echo "$0: unexpected args: $*" >&2 ; usage 1 ;; + esac + shift +done + +##### end command line parsing ######## ret=0 ##### begin setup fstab for subvols we care about ###### -first_root_crypt=$(awk '$2 == "/" {print $1}' /etc/mtab) +root_dev=$(awk '$2 == "/" {print $1}' /etc/mtab) +if [[ $root_dev == /dev/dm-* ]]; then + for d in /dev/mapper/*; do + if [[ $(readlink -f $d) == "$root_dev" ]]; then + root_dev=$d + break + fi + done +fi + +if cryptsetup status $root_dev &>/dev/null; then + crypt_dev=$root_dev +else # if we are in a recovery boot, find the next best crypt device + noauto=,noauto + for dev in $(dmsetup ls --target crypt | awk '{print $1}'); do + dev=/dev/mapper/$dev + if awk '{print $1}' /etc/mtab | grep -Fx $dev &>/dev/null; then + crypt_dev=$dev + break + fi + done +fi + + fstab </dev/null); then mnt $d for b in ${binds[@]}; do mnt $b @@ -208,25 +235,18 @@ for vol in q a o i; do continue fi - fresh_snap=$(=0; i--)); do + if [[ $parentid == $(btrfs sub show ${bsubs[i]} | awk '$1 == "UUID:" {print $2}') ]]; then + bsub=${bsubs[i]} + break + fi + done + if [[ $bsub ]]; then + tmp=$(mktemp) + # in testing, same subvol is 136 bytes. allow some overhead + btrfs send --no-data -p $bsub $leaf | head -c 1000 > $tmp || [[ $? == 141 ]] + if (( $(stat -c%s $tmp) < 1000)); then + # example output for an empty diff: + # Found a valid Btrfs stream header, version 1 + # o.leaf.2019-05-15T14:00:50-0400;snapshot: uuid=ba045ea30737dd449003f1ee40ec12d0, ctrasid=109533, clone_uuid=3c7e3544e486834aa71d89e5b8f30056, clone_ctransid=109533 + lines=$(/a/opt/btrfs-snapshots-diff/btrfs-snapshots-diff.py -s -f $tmp | \ + grep -vxF "Found a valid Btrfs stream header, version 1" | \ + grep -cv "^[^;]*;snapshot: ") ||: + if [[ $lines == 0 ]]; then + x btrfs sub del $leaf + fi + fi + fi + fi + ### end check if leaf is different, delete it if not ### + + ## begin expire leaf vols ## leaf_vols=($vol.leaf.*) + count=1 for leaf in ${leaf_vols[@]}; do leaf_secs=$(date -d ${leaf#$vol.leaf.} +%s) - if (( $(date +%s) - 60*60*24*60 > leaf_secs )); then # 60 days - e btrfs sub del $leaf + if (( $(date +%s) - 60*60*24*60 > leaf_secs || count > 200 )); then # 60 days + x btrfs sub del $leaf fi + count=$((count+1)) done + ## end expire leaf vols ## fi + #### end dealing with leaf vols #### + # Note, we make a few assumptions in this script, like # $d was not a different subvol id than $vol, and # things otherwise didn't get mounted very strangely. - e btrfs sub snapshot $fresh_snap $vol + m btrfs sub snapshot $fresh_snap $vol for dir in $d ${binds[@]}; do - e mnt $dir + m mnt $dir done stale_dir=/nocow/btrfs-stale rm -f $stale_dir/$d + done ### disabled