various changes around data volumes
[distro-setup] / mount-latest-subvol
1 #!/bin/bash
2
3 [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
4
5 errcatch() {
6 set -E; shopt -s extdebug
7 _err-trap() {
8 err=$?
9 exec >&2
10 set +x
11 echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}:in \`$BASH_COMMAND' returned $err"
12 bash-trace 2
13 echo "$0: exiting with code $err"
14 exit $err
15 }
16 trap _err-trap ERR
17 set -o pipefail
18 }
19 bash-trace() {
20 local -i argc_index=0 arg frame i start=${1:-1} max_indent=8 indent
21 local source
22 local extdebug=false
23 if [[ $(shopt -p extdebug) == *-s* ]]; then
24 extdebug=true
25 fi
26
27 for ((frame=0; frame < ${#FUNCNAME[@]}-1; frame++)); do
28 argc=${BASH_ARGC[frame]}
29 argc_index+=$argc
30 ((frame < start)) && continue
31 if (( ${#BASH_SOURCE[@]} > 1 )); then
32 source="${BASH_SOURCE[frame+1]}:${BASH_LINENO[frame]}:"
33 fi
34 indent=$((frame-start+1))
35 indent=$((indent < max_indent ? indent : max_indent))
36 printf "%${indent}s↳%sin \`%s" '' "$source" "${FUNCNAME[frame]}"
37 if $extdebug; then
38 for ((i=argc_index-1; i >= argc_index-argc; i--)); do
39 printf " %s" "${BASH_ARGV[i]}"
40 done
41 fi
42 echo \'
43 done
44 }
45 errcatch
46
47 tu() {
48 while read -r line; do
49 file="$1"
50 grep -xFq "$line" "$file" || tee -a "$file"<<<"$line"
51 done
52 }
53 e() { printf "%s\n" "$*"; "$@"; }
54 mnt() {
55 dir=$1
56 if ! mountpoint $dir >/dev/null; then
57 mkdir -p $dir
58 e mount $dir
59 fi
60 }
61
62 ret=0
63
64 first_root_crypt=$(awk '$2 == "/" {print $1}' /etc/mtab)
65 tu /etc/fstab <<EOF
66 $first_root_crypt /q btrfs noatime,subvol=q 0 0
67 /q/a /a none bind 0 0
68 EOF
69 case $HOSTNAME in
70 treetowl|x2|frodo)
71 tu /etc/fstab <<EOF
72 $first_root_crypt /p btrfs noatime,subvol=p 0 0
73 EOF
74 ;;
75 esac
76
77 for vol in q p; do
78 d=/$vol
79 if ! awk '{print $2}' /etc/fstab | grep -xF $d &>/dev/null; then
80 continue
81 fi
82
83
84 binds=()
85 roots=($d)
86 while true; do
87 new_roots=()
88 for r in ${roots[@]}; do
89 # /q/a /a none bind 0 0
90 new_roots+=($(sed -rn "s#^$r/\S+\s+(\S+)\s+none\s+bind\s.*#\1#p" /etc/fstab))
91 done
92 (( ${#new_roots} )) || break
93 binds+=(${new_roots[@]})
94 roots=( ${new_roots[@]} )
95 done
96
97 if e check-subvol-stale $d; then
98 for b in ${binds[@]}; do
99 mnt $b
100 done
101 continue
102 fi
103
104 last_snap=$(</nocow/btrfs-stale/$vol)
105 if [[ ! $last_snap ]]; then
106 echo "$0: error. empty last_snap var"
107 ret=1
108 continue
109 fi
110
111 umount_ret=true
112 unmounted=()
113 for dir in $(echo $d ${binds[*]}\ |tac -s\ ); do
114 if mountpoint $dir; then
115 if e umount -R $dir; then
116 unmounted+=($dir)
117 else
118 umount_ret=false
119 echo "$0: failed to umount $dir"
120 break
121 fi
122 fi
123 done
124
125 if ! $umount_ret; then
126 for dir in ${unmounted[@]}; do
127 mnt $dir
128 done
129 ret=1
130 continue
131 fi
132
133 cd /mnt/root
134 if [[ -e $vol ]]; then
135 e btrfs sub del $vol
136 fi
137 # Note, we make a few assumptions in this script, like
138 # $d was not a different subvol id than $vol, and
139 # things otherwise didn't get mounted very strangely.
140 e btrfs sub snapshot btrbk/$last_snap $vol
141 for dir in $d ${binds[@]}; do
142 e mnt $dir
143 done
144 done
145
146 if [[ $HOSTNAME == treetowl ]]; then
147 # partitioned it with fai partitioner outside of fai,
148 # because it\'s worth it to have 1% space reserved for boot and
149 # swap partitions in case I ever want to boot off those drives.
150 # as root:
151 # . /a/bin/fai/fai-wrapper
152 # eval-fai-classfile /a/bin/fai/fai/config/class/51-multi-boot
153 # fai-setclass ROTATIONAL
154 # export LUKS_DIR=/q/root/luks/
155 # # because the partition nums existed already
156 # fai-setclass REPARTITION
157 # /a/bin/fai/fai/config/hooks/partition.DEFAULT
158
159 devs=(
160 ata-TOSHIBA_MD04ACA500_84REK6NTFS9A-part1
161 ata-TOSHIBA_MD04ACA500_84R2K773FS9A-part1
162 ata-TOSHIBA_MD04ACA500_8471K430FS9A-part1
163 ata-TOSHIBA_MD04ACA500_8481K493FS9A-part1
164 )
165 first=true
166 for dev in ${devs[@]}; do
167 if $first; then
168 first=false
169 tu /etc/fstab <<EOF
170 /dev/mapper/crypt_dev_$dev /i btrfs noatime,subvol=i,noauto 0 0
171 /dev/mapper/crypt_dev_$dev /mnt/iroot btrfs noatime,subvolid=0,noauto 0 0
172 EOF
173 fi
174 tu /etc/crypttab <<EOF
175 crypt_dev_$dev /dev/disk/by-id/$dev /q/root/luks/host-treetowl discard,luks
176 EOF
177 if [[ ! -e /dev/mapper/crypt_dev_$dev ]]; then
178 cryptdisks_start crypt_dev_$dev
179 fi
180 done
181 else
182 tu /etc/fstab <<'EOF'
183 /q/i /i none bind,noauto 0 0
184 EOF
185 fi
186
187 exit $ret