diff options
Diffstat (limited to 'src/initrd/umountall.sh')
-rwxr-xr-x | src/initrd/umountall.sh | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/initrd/umountall.sh b/src/initrd/umountall.sh new file mode 100755 index 0000000..bf89838 --- /dev/null +++ b/src/initrd/umountall.sh | |||
@@ -0,0 +1,126 @@ | |||
1 | #!/bin/sh | ||
2 | OPEN_SHELL_BEFORE_SHUTDOWN= | ||
3 | |||
4 | movemount() { | ||
5 | if mountpoint -q "$1"; then | ||
6 | umount /root/"$1" | ||
7 | else | ||
8 | mkdir -p "$1" | ||
9 | mount --move /root/"$1" "$1" | ||
10 | fi | ||
11 | } | ||
12 | |||
13 | retry_n_delay() { | ||
14 | local n="$1" delay="$2" | ||
15 | shift 2 | ||
16 | while [ "$n" -gt 0 ]; do "$@" && break; sleep $delay; n=$((n-1)); done | ||
17 | } | ||
18 | |||
19 | umount_all_novirtual() | ||
20 | { | ||
21 | # EQUIVALENT: umount -a -t norootfs,nosysfs,noproc,notmpfs,nodevpts,nodevtmpfs | ||
22 | # busyboxy umount does not support -t, therefore: | ||
23 | tac /proc/mounts | { | ||
24 | errors=0 | ||
25 | while read dev mp type opts _; do | ||
26 | case $type in | ||
27 | rootfs|sysfs|proc|tmpfs|devpts|devtmpfs) ;; | ||
28 | *) umount "$mp" || errors=$((errors+1)) ;; | ||
29 | esac | ||
30 | done | ||
31 | return $errors | ||
32 | } | ||
33 | } | ||
34 | |||
35 | losetup_delete_all() | ||
36 | { | ||
37 | local f dev | ||
38 | for f in /sys/dev/block/7:*/loop; do | ||
39 | dev=${f#/sys/dev/block/7:} | ||
40 | dev=/dev/loop${dev%%/*} | ||
41 | losetup -d $dev | ||
42 | done | ||
43 | } | ||
44 | |||
45 | mdadm_stop_all() | ||
46 | { | ||
47 | for md in /dev/md* /dev/md/*; do | ||
48 | test -b "$md" && mdadm --stop "$md" | ||
49 | done | ||
50 | } | ||
51 | |||
52 | lvm_deactivate() { lvm lvchange -v -an samizdat 11>&-; } | ||
53 | |||
54 | killemdead() { | ||
55 | force= pids="$(pidof "$@")" | ||
56 | while [ "$pids" ]; do | ||
57 | kill $force $pids | ||
58 | living= | ||
59 | for p in $pids; do | ||
60 | if [ -e /proc/$p ]; then | ||
61 | living=1 | ||
62 | break | ||
63 | fi | ||
64 | done | ||
65 | [ ! "$living" ] && break | ||
66 | force=-9 | ||
67 | done | ||
68 | } | ||
69 | |||
70 | specials= movemounts= umounts= | ||
71 | while read dev mp type opts _; do # N.B. order is reversed in variables | ||
72 | case $mp in | ||
73 | /root/dev|/root/proc) | ||
74 | specials="$mp $specials" ;; | ||
75 | /root/sys|/root/cdrom|/root/mnt/*|/root/gpg|/root/overlay|/root/xino|/root/squashes/*) | ||
76 | movemounts="$mp $movemounts" ;; | ||
77 | /root/*) | ||
78 | umounts="$mp $umounts" ;; | ||
79 | esac | ||
80 | done < /proc/mounts | ||
81 | |||
82 | # Unmount mounts under /root that we didn't put there | ||
83 | while true; do | ||
84 | error=0; success=0 | ||
85 | for m in $umounts; do | ||
86 | if umount $m; then | ||
87 | success=$((success+1)) | ||
88 | else | ||
89 | error=$((error+1)) | ||
90 | fi | ||
91 | done | ||
92 | [ $error = 0 ] && break | ||
93 | [ $success = 0 ] && break | ||
94 | done | ||
95 | |||
96 | # Move back mounts that we moved | ||
97 | for m in $movemounts; do | ||
98 | movemount "${m#/root}" # TODO: error handling | ||
99 | done | ||
100 | |||
101 | killemdead gpg-agent samizdat-pinentry | ||
102 | |||
103 | umount /root/dev | ||
104 | umount /root/proc | ||
105 | ln -sf /proc/mounts /etc/mtab | ||
106 | |||
107 | umount_all_novirtual | ||
108 | mdadm_stop_all | ||
109 | losetup_delete_all | ||
110 | lvm_deactivate | ||
111 | cryptsetup remove samizdatcrypt | ||
112 | losetup_delete_all | ||
113 | umount_all_novirtual | ||
114 | |||
115 | if [ "$OPEN_SHELL_BEFORE_SHUTDOWN" ]; then | ||
116 | read cmd < /halt | ||
117 | echo | ||
118 | echo "Remove cdrom and press ctrl-d to run '$cmd'." | ||
119 | /bin/sh -i | ||
120 | fi | ||
121 | |||
122 | read cmd < /halt && $cmd | ||
123 | sleep 1 | ||
124 | |||
125 | echo "Error! Starting emergency shell with pid 1." | ||
126 | exec /bin/sh -i | ||