blob: e13e6fbe53201ada981962baca33f0d168f57938 (
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
|
#!/usr/bin/ash
# 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)
read devname <"$1/dm/name"
cryptsetup remove "$devname"
;;
dm)
read devname <"$1/dm/name"
dmsetup remove "$devname"
;;
lvm)
# disassemble the parent VG
read devname <"$1/dm/name"
lvm lvdisplay -c "/dev/mapper/$devname" | {
IFS=: read _ vgname _
lvm vgchange --noudevsync -an "$vgname"
}
;;
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 metadata _ < "/sys/class/block/$1/md/metadata_version"
if [ "$metadata" = external ]; then
mdadm --wait-clean "/dev/$1"
fi
mdadm --stop "/dev/$1"
;;
dmraid)
read 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
}
# XXX: Discourage libdevmapper from thinking that udev
# might be in a useful state. FS#30995.
rm -rf /run/udev
# chdir, so that we can avoid a lot of path chopping
cd /sys/class/block
printf '%s\n' 'Detaching loop devices.'
for loop in loop*/loop; do
[ -e "$loop" ] && losetup -d "${loop%/loop}"
done
printf '%s\n' "Unmounting all devices."
# unmount everything in /oldroot
findmnt -Rruno TARGET /oldroot | awk '
BEGIN { i = 0 }
{
i++
mounts[i] = $0
}
END {
for (j = i; j > 0; j--) {
print mounts[j]
}
}
' | while read -r mount; do
umount "$mount"
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
|