-
Notifications
You must be signed in to change notification settings - Fork 62
/
shutdown
108 lines (89 loc) · 2.76 KB
/
shutdown
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
#!/usr/bin/ash
# SPDX-License-Identifier: GPL-2.0-only
# teardown a single device by node name
# $1: device node name, e.g. md0, dm-2
stop_device() {
local devtype='' devname=''
# the device must still be active
[ -e "/sys/class/block/$1" ] || return 1
# this can sometimes fail on stopped md devices, when the
# sysfs node doesn't go away as quickly as i'd like it to.
devtype="$(lsblk -drno TYPE "/dev/$1" 2>/dev/null)" || return 1
case "$devtype" in
crypt)
# dmsetup could be used here, but we don't know that it
# exists.
read -r devname <"$1/dm/name"
cryptsetup remove "$devname"
;;
lvm | dm)
read -r devname <"$1/dm/name"
dmsetup --noudevsync remove "$devname"
;;
raid*)
# wait for arrays with external metadata to be marked as
# clean. unfortunately, there isn't a whole lot we can do
# if this fails, and the array may need a full rebuild on
# the next reboot.
IFS=: read -r metadata _ <"/sys/class/block/$1/md/metadata_version"
if [ "$metadata" = external ]; then
mdadm --wait-clean "/dev/$1"
fi
mdadm --stop "/dev/$1"
;;
dmraid)
read -r devname <"$1/dm/name"
dmraid -an "$devname"
;;
# silently ignore unstacked devices
esac
}
# recursively disassemble a device chain
# $1: device node name, e.g. md0, dm-2
disassemble() {
local holder=''
for holder in "$1"/holders/*; do
[ -e "$holder" ] && disassemble "${holder##*/}"
stop_device "$1"
done
}
copy_binary_from_host() {
local bin="$1"
# hardcode a sane PATH
for p in '/usr/sbin' '/usr/bin' '/sbin' '/bin'; do
if [ -e "/oldroot/$p/$bin" ]; then
cp "/oldroot/$p/$bin" "/usr/bin/$1"
return 0
fi
done
return 1
}
# XXX: Discourage libdevmapper from thinking that udev
# might be in a useful state. FS#30995.
rm -rf /run/udev
if [ "$1" = kexec ] && ! command -v kexec >/dev/null; then
copy_binary_from_host kexec
fi
# chdir, so that we can avoid a lot of path chopping
cd /sys/class/block || exit
printf '%s\n' "Unmounting all devices."
umount --recursive /oldroot
printf '%s\n' 'Detaching loop devices.'
for loop in loop*/loop; do
[ -e "$loop" ] && losetup -d "${loop%/loop}"
done
printf '%s\n' "Disassembling stacked devices."
# iterate over devices with holders
for part in */holders/*; do
[ -e "$part" ] && disassemble "${part%%/*}"
done
case "$1" in
poweroff | shutdown | halt)
"$1" -f
;;
*)
type kexec >/dev/null && kexec -e
reboot -f
;;
esac
# vim: ft=sh ts=4 sw=4