summaryrefslogtreecommitdiff
path: root/src/initrd/umountall.sh
blob: bf898384af0de2936e98a3861334ec0ac690a64c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/bin/sh
OPEN_SHELL_BEFORE_SHUTDOWN=

movemount() {
  if mountpoint -q "$1"; then
    umount /root/"$1"
  else
    mkdir -p "$1"
    mount --move /root/"$1" "$1"
  fi
}

retry_n_delay() {
  local n="$1" delay="$2"
  shift 2
  while [ "$n" -gt 0 ]; do "$@" && break; sleep $delay; n=$((n-1)); done
}

umount_all_novirtual()
{
  # EQUIVALENT: umount -a -t norootfs,nosysfs,noproc,notmpfs,nodevpts,nodevtmpfs
  # busyboxy umount does not support -t, therefore:
  tac /proc/mounts | {
    errors=0
    while read dev mp type opts _; do
      case $type in
	rootfs|sysfs|proc|tmpfs|devpts|devtmpfs) ;;
	*) umount "$mp" || errors=$((errors+1)) ;;
      esac
    done 
    return $errors
  }
}

losetup_delete_all()
{
  local f dev
  for f in /sys/dev/block/7:*/loop; do
    dev=${f#/sys/dev/block/7:}
    dev=/dev/loop${dev%%/*}
    losetup -d $dev
  done
}

mdadm_stop_all()
{
  for md in /dev/md* /dev/md/*; do 
    test -b "$md" && mdadm --stop "$md"
  done
}

lvm_deactivate() { lvm lvchange -v -an samizdat 11>&-; }

killemdead() {
  force= pids="$(pidof "$@")"
  while [ "$pids" ]; do
    kill $force $pids
    living=
    for p in $pids; do
      if [ -e /proc/$p ]; then
	living=1
	break
      fi
    done
    [ ! "$living" ] && break
    force=-9
  done
}

specials= movemounts= umounts=
while read dev mp type opts _; do # N.B. order is reversed in variables
case $mp in
  /root/dev|/root/proc)
    specials="$mp $specials" ;;
  /root/sys|/root/cdrom|/root/mnt/*|/root/gpg|/root/overlay|/root/xino|/root/squashes/*) 
    movemounts="$mp $movemounts" ;; 
  /root/*)
    umounts="$mp $umounts" ;;
esac
done < /proc/mounts

# Unmount mounts under /root that we didn't put there
while true; do
  error=0; success=0
  for m in $umounts; do
    if umount $m; then
      success=$((success+1))
    else
      error=$((error+1))
    fi
  done
  [ $error = 0 ] && break
  [ $success = 0 ] && break
done

# Move back mounts that we moved
for m in $movemounts; do
  movemount "${m#/root}" # TODO: error handling
done

killemdead gpg-agent samizdat-pinentry

umount /root/dev
umount /root/proc
ln -sf /proc/mounts /etc/mtab

umount_all_novirtual
mdadm_stop_all
losetup_delete_all
lvm_deactivate
cryptsetup remove samizdatcrypt
losetup_delete_all
umount_all_novirtual

if [ "$OPEN_SHELL_BEFORE_SHUTDOWN" ]; then
  read cmd < /halt
  echo
  echo "Remove cdrom and press ctrl-d to run '$cmd'."
  /bin/sh -i
fi

read cmd < /halt && $cmd
sleep 1

echo "Error!  Starting emergency shell with pid 1."
exec /bin/sh -i