summaryrefslogtreecommitdiff
path: root/files/initramfs-scripts/shutdown
blob: 0065bcc8ffe26bf5d61d13b4ba9c2e741c1dc8ad (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
#!/bin/sh

fail(){
    echo "$@" >&2
    # The behaviour on failure of systemd when shutting down without a
    # shutdownramfs is to freeze if it fails, but the behaviour of an initramfs
    # on failure is to drop you into a recovery shell. The latter seems more
    # useful.
    exec /bin/sh
}

startswith(){
    # Filter out lines that don't start with $1
    # grep ^EXPR is usually sufficient, but would require escaping of EXPR.
    # Instead this compares the line to the line with its prefix stripped,
    # so if the line is different, then it started with that prefix.
    # It's ugly, but is less logic than escaping the regular expression and
    # using grep, more reliable than not making any effort to escape, and
    # less surprising than requiring the parameter to be pre-escaped.
    while read -r line; do
        if [ "${line#"$1"}" != "$line" ]; then
            printf '%s\n' "$line"
        fi
    done
}

recursive_umount(){
    # Recursively unmount every mountpoint under $1.
    # This works by filtering to select mountpoints from mountinfo that start
    # with the absolute path of the directory given.
    # It unmounts in reverse-order, so that it may unmount dependent mounts
    # first, and it has to handle the paths having octal escape sequences.
    set -- "$(readlink -f "$1")"
    cut -d' ' -f5 /proc/self/mountinfo | startswith "$1" \
        | sort -r | while read -r mp; do
        umount "$(echo -e "$mp")"
    done
}

# Give the rootfs another chance to write its state to disk.
sync

# Kill any http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/
# as we don't have any facility to cleanly shut them down in this initramfs.
killall5

# Recursively unmount the old root, so they have a chance of performing
# unmount-time cleanup.
recursive_umount /oldroot

case "$1" in
reboot|poweroff|halt)
        if ! "$1" -f; then
            fail "$1 command failed"
        fi
        ;;
kexec)
        # probably don't have this, but we'll try anyway
        if ! kexec -e; then
            fail "$1 command failed"
        fi
        ;;
*)
        fail "Unrecognized shutdown verb $1"
        ;;
esac