forked from vianney/arch-luks-suspend
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathdebian-luks-suspend
executable file
·165 lines (129 loc) · 4.41 KB
/
debian-luks-suspend
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/bin/bash
set -u
trap 'echo "Press ENTER to continue."; read dummy' ERR
INITRAMFS_DIR="/run/initramfs/"
INITRAMFS_DIR_ORIG=${INITRAMFS_DIR}
SYSTEM_SLEEP_PATH=/lib/systemd/system-sleep
SYSTEM_SLEEP_BINARY=/lib/systemd/systemd-sleep
SUSPEND_SCRIPT=bin/encrypt-on-suspend
BIND_PATHS="/sys /proc /dev /run"
REMOUNT=0
CRYPTNAME="$(pvdisplay -C -o pv_name --noheadings | tr -d ' ' | cut -d\/ -f4)"
CHROOT_ARGS=""
# run_dir DIR ARGS...
# Run all executable scripts in directory DIR with arguments ARGS
run_dir() {
local dir=$1
shift
find "${dir}" -type f -executable -exec "{}" "$@" ";"
}
ext4_cryptdevice_mount_options() {
local mt="$(grep "^${1} " /proc/mounts | cut -d ' ' -f 3,4)"
if [[ "${mt:0:5}" == "ext4 " ]]; then
echo "${mt:5}"
fi
}
mount_initramfs() {
local INITRAMFS=$1
mounted=`mount | grep $INITRAMFS_DIR`
if [[ $? -eq 0 ]] ; then
return
fi
if [[ ! -e "$INITRAMFS_DIR" ]] ; then
mkdir "$INITRAMFS_DIR"
chmod 700 "$INITRAMFS_DIR"
fi
mount -t tmpfs -o size=512m tmpfs ${INITRAMFS_DIR}
unmkinitramfs "${INITRAMFS}" "${INITRAMFS_DIR}"
if [[ -d ${INITRAMFS_DIR}/main ]] ; then
INITRAMFS_DIR_ORIG=${INITRAMFS_DIR}
INITRAMFS_DIR=${INITRAMFS_DIR}/main
fi
for p in ${BIND_PATHS}; do
mkdir -p "${INITRAMFS_DIR}${p}"
mount -o bind ${p} "${INITRAMFS_DIR}${p}"
done
}
unmount_initramfs() {
if [[ "${INITRAMFS_DIR_ORIG}" != "${INITRAMFS_DIR}" ]] ; then
INITRAMFS_DIR=${INITRAMFS_DIR_ORIG}
fi
umount -R ${INITRAMFS_DIR}
}
service_is_running() {
systemctl is-active --quiet "$1"
echo $?
}
parse_command_line() {
for i in "$@" ; do
case $i in
-g|--gui)
CHROOT_ARGS=" -g"
;;
esac
done
}
## Main script
loginctl lock-sessions
parse_command_line "$@"
# parse boot command line into $kernel_cmdline
declare -A kernel_cmdline
for x in $(cat /proc/cmdline) ; do
kernel_cmdline[$(echo $x | cut -f1 -d=)]=$(echo $x | cut -f2 -d=)
done
# clean up the terminal if a quiet console is requested
[[ -n "${kernel_cmdline[quiet]+x}" ]] && TERM=linux clear
# Retrieve cryptdevice name from boot command line
ROOT_CRYPT_DEVICE=${kernel_cmdline[root]}
# extract initramfs to switch to during suspend
INITRAMFS=`echo "/boot/${kernel_cmdline[BOOT_IMAGE]//vmlinuz/initrd.img}"`
mount_initramfs $INITRAMFS
[ -e "${INITRAMFS_DIR}/$SUSPEND_SCRIPT" ] || exec $SYSTEM_SLEEP_BINARY suspend
# Run pre-suspend scripts
run_dir "${SYSTEM_SLEEP_PATH}" pre suspend
# Stop udev service and prevent it to be autostarted.
# Otherwise, luksResume will hang waiting for udev, which is itself waiting
# for I/O on the root device.
bluetooth_state=`service_is_running bluetooth`
if [ $bluetooth_state -eq 0 ] ; then
systemctl stop bluetooth
fi
systemctl stop NetworkManager-dispatcher
systemctl stop NetworkManager
systemctl stop systemd-udevd-control.socket
systemctl stop systemd-udevd-kernel.socket
systemctl stop systemd-udevd.service
# Journalled ext4 filesystems in kernel versions 3.11+ will block suspend
# if mounted with `barrier=1`, which is the default. Temporarily remount with
# `barrier=0` if this is true of the crypt fs.
MOUNT_OPTS="$(ext4_cryptdevice_mount_options "$ROOT_CRYPT_DEVICE")"
if [[ "$MOUNT_OPTS" ]] && ! [[ "$MOUNT_OPTS" == *nobarrier* || "$MOUNT_OPTS" == *barrier=0* ]]; then
REMOUNT=1
mount -o remount,"$MOUNT_OPTS",barrier=0 /
fi
# If we have a kernel that supports manual sync before suspend, enable it
[ -e /sys/power/sync_on_suspend ] && echo "0" > /sys/power/sync_on_suspend
# Hand over execution to script inside initramfs
# Nice it to help reduce race conditions
(cd "${INITRAMFS_DIR}" && nice -n -20 chroot . /$SUSPEND_SCRIPT $CRYPTNAME $CHROOT_ARGS)
[ -e /sys/power/sync_on_suspend ] && echo "1" > /sys/power/sync_on_suspend
# Restore original mount options if necessary
if ((REMOUNT)); then
mount -o remount,"$MOUNT_OPTS",barrier=1 /
fi
# Quit the temporary udev process from the chroot
udevadm control --exit
# Restart services
systemctl start systemd-udevd-control.socket
systemctl start systemd-udevd-kernel.socket
systemctl start systemd-udevd.service
systemctl start NetworkManager
systemctl start NetworkManager-dispatcher
if [ $bluetooth_state -eq 0 ] ; then
systemctl start bluetooth
fi
# Run post-suspend scripts
run_dir "${SYSTEM_SLEEP_PATH}" post suspend
unmount_initramfs
# Unlock user sessions
loginctl unlock-sessions