]>
Commit | Line | Data |
---|---|---|
16692e6b | 1 | #!/bin/sh |
eda3d4e1 | 2 | |
245529d8 | 3 | command -v getarg >/dev/null || . /lib/dracut-lib.sh || . /usr/lib/dracut/modules.d/99base/dracut-lib.sh |
d402c18d MAR |
4 | command -v getargbool >/dev/null || { |
5 | # Compatibility with older Dracut versions. | |
6 | # With apologies to the Dracut developers. | |
7 | getargbool() { | |
d402c18d | 8 | _default="$1"; shift |
2ca77988 | 9 | ! _b=$(getarg "$@") && [ -z "$_b" ] && _b="$_default" |
d402c18d | 10 | if [ -n "$_b" ]; then |
41532e5a KP |
11 | [ "$_b" = "0" ] && return 1 |
12 | [ "$_b" = "no" ] && return 1 | |
13 | [ "$_b" = "off" ] && return 1 | |
d402c18d MAR |
14 | fi |
15 | return 0 | |
16 | } | |
17 | } | |
eda3d4e1 ST |
18 | |
19 | OLDIFS="${IFS}" | |
20 | NEWLINE=" | |
21 | " | |
d8ced661 | 22 | TAB=" " |
eda3d4e1 ST |
23 | |
24 | ZPOOL_IMPORT_OPTS="" | |
25 | if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then | |
41532e5a KP |
26 | warn "ZFS: Will force-import pools if necessary." |
27 | ZPOOL_IMPORT_OPTS="${ZPOOL_IMPORT_OPTS} -f" | |
eda3d4e1 ST |
28 | fi |
29 | ||
30 | # find_bootfs | |
31 | # returns the first dataset with the bootfs attribute. | |
32 | find_bootfs() { | |
41532e5a KP |
33 | IFS="${NEWLINE}" |
34 | for dataset in $(zpool list -H -o bootfs); do | |
35 | case "${dataset}" in | |
36 | "" | "-") | |
37 | continue | |
38 | ;; | |
39 | "no pools available") | |
40 | IFS="${OLDIFS}" | |
41 | return 1 | |
42 | ;; | |
43 | *) | |
44 | IFS="${OLDIFS}" | |
45 | echo "${dataset}" | |
46 | return 0 | |
47 | ;; | |
48 | esac | |
49 | done | |
50 | ||
51 | IFS="${OLDIFS}" | |
52 | return 1 | |
eda3d4e1 ST |
53 | } |
54 | ||
55 | # import_pool POOL | |
56 | # imports the given zfs pool if it isn't imported already. | |
57 | import_pool() { | |
d8ced661 | 58 | pool="${1}" |
eda3d4e1 | 59 | |
41532e5a KP |
60 | if ! zpool list -H "${pool}" > /dev/null 2>&1; then |
61 | info "ZFS: Importing pool ${pool}..." | |
6fc30992 | 62 | # shellcheck disable=SC2086 |
41532e5a KP |
63 | if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${pool}" ; then |
64 | warn "ZFS: Unable to import pool ${pool}" | |
65 | return 1 | |
66 | fi | |
67 | fi | |
eda3d4e1 | 68 | |
41532e5a | 69 | return 0 |
eda3d4e1 ST |
70 | } |
71 | ||
d8ced661 | 72 | _mount_dataset_cb() { |
34eef3e9 | 73 | # shellcheck disable=SC2154 |
d8ced661 AZ |
74 | mount -o zfsutil -t zfs "${1}" "${NEWROOT}${2}" |
75 | } | |
76 | ||
eda3d4e1 ST |
77 | # mount_dataset DATASET |
78 | # mounts the given zfs dataset. | |
79 | mount_dataset() { | |
d8ced661 | 80 | dataset="${1}" |
41532e5a | 81 | mountpoint="$(zfs get -H -o value mountpoint "${dataset}")" |
d8ced661 | 82 | ret=0 |
eda3d4e1 | 83 | |
41532e5a KP |
84 | # We need zfsutil for non-legacy mounts and not for legacy mounts. |
85 | if [ "${mountpoint}" = "legacy" ] ; then | |
d8ced661 | 86 | mount -t zfs "${dataset}" "${NEWROOT}" || ret=$? |
41532e5a | 87 | else |
d8ced661 AZ |
88 | mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}" || ret=$? |
89 | ||
90 | if [ "$ret" = "0" ]; then | |
91 | for_relevant_root_children "${dataset}" _mount_dataset_cb || ret=$? | |
92 | fi | |
41532e5a | 93 | fi |
eda3d4e1 | 94 | |
34eef3e9 | 95 | return "${ret}" |
d8ced661 AZ |
96 | } |
97 | ||
98 | # for_relevant_root_children DATASET EXEC | |
99 | # Runs "EXEC dataset mountpoint" for all children of DATASET that are needed for system bringup | |
100 | # Used by zfs-generator.sh and friends, too! | |
101 | for_relevant_root_children() { | |
102 | dataset="${1}" | |
103 | exec="${2}" | |
104 | ||
105 | zfs list -t filesystem -Ho name,mountpoint,canmount -r "${dataset}" | | |
106 | ( | |
107 | _ret=0 | |
108 | while IFS="${TAB}" read -r dataset mountpoint canmount; do | |
109 | [ "$canmount" != "on" ] && continue | |
110 | ||
111 | case "$mountpoint" in | |
112 | /etc|/bin|/lib|/lib??|/libx32|/usr) | |
113 | # If these aren't mounted we may not be able to get to the real init at all, or pollute the dataset holding the rootfs | |
114 | "${exec}" "${dataset}" "${mountpoint}" || _ret=$? | |
115 | ;; | |
116 | *) | |
117 | # Up to the real init to remount everything else it might need | |
118 | ;; | |
119 | esac | |
120 | done | |
34eef3e9 | 121 | exit "${_ret}" |
d8ced661 | 122 | ) |
eda3d4e1 ST |
123 | } |
124 | ||
7280d581 KP |
125 | # ask_for_password |
126 | # | |
127 | # Wraps around plymouth ask-for-password and adds fallback to tty password ask | |
128 | # if plymouth is not present. | |
129 | # | |
130 | # --cmd command | |
131 | # Command to execute. Required. | |
132 | # --prompt prompt | |
133 | # Password prompt. Note that function already adds ':' at the end. | |
134 | # Recommended. | |
135 | # --tries n | |
136 | # How many times repeat command on its failure. Default is 3. | |
137 | # --ply-[cmd|prompt|tries] | |
138 | # Command/prompt/tries specific for plymouth password ask only. | |
139 | # --tty-[cmd|prompt|tries] | |
140 | # Command/prompt/tries specific for tty password ask only. | |
141 | # --tty-echo-off | |
142 | # Turn off input echo before tty command is executed and turn on after. | |
143 | # It's useful when password is read from stdin. | |
144 | ask_for_password() { | |
41532e5a KP |
145 | ply_tries=3 |
146 | tty_tries=3 | |
147 | while [ "$#" -gt 0 ]; do | |
7280d581 KP |
148 | case "$1" in |
149 | --cmd) ply_cmd="$2"; tty_cmd="$2"; shift;; | |
150 | --ply-cmd) ply_cmd="$2"; shift;; | |
151 | --tty-cmd) tty_cmd="$2"; shift;; | |
152 | --prompt) ply_prompt="$2"; tty_prompt="$2"; shift;; | |
153 | --ply-prompt) ply_prompt="$2"; shift;; | |
154 | --tty-prompt) tty_prompt="$2"; shift;; | |
155 | --tries) ply_tries="$2"; tty_tries="$2"; shift;; | |
156 | --ply-tries) ply_tries="$2"; shift;; | |
157 | --tty-tries) tty_tries="$2"; shift;; | |
158 | --tty-echo-off) tty_echo_off=yes;; | |
34eef3e9 | 159 | *) echo "ask_for_password(): wrong opt '$1'" >&2;; |
7280d581 KP |
160 | esac |
161 | shift | |
162 | done | |
163 | ||
245529d8 AZ |
164 | { |
165 | flock -s 9 | |
166 | ||
7280d581 | 167 | # Prompt for password with plymouth, if installed and running. |
16692e6b | 168 | if plymouth --ping 2>/dev/null; then |
7280d581 | 169 | plymouth ask-for-password \ |
f20fb199 MV |
170 | --prompt "$ply_prompt" --number-of-tries="$ply_tries" | \ |
171 | eval "$ply_cmd" | |
7280d581 KP |
172 | ret=$? |
173 | else | |
174 | if [ "$tty_echo_off" = yes ]; then | |
175 | stty_orig="$(stty -g)" | |
176 | stty -echo | |
177 | fi | |
178 | ||
41532e5a KP |
179 | i=1 |
180 | while [ "$i" -le "$tty_tries" ]; do | |
7280d581 | 181 | [ -n "$tty_prompt" ] && \ |
41532e5a | 182 | printf "%s [%i/%i]:" "$tty_prompt" "$i" "$tty_tries" >&2 |
7280d581 KP |
183 | eval "$tty_cmd" && ret=0 && break |
184 | ret=$? | |
41532e5a | 185 | i=$((i+1)) |
7280d581 KP |
186 | [ -n "$tty_prompt" ] && printf '\n' >&2 |
187 | done | |
41532e5a KP |
188 | unset i |
189 | [ "$tty_echo_off" = yes ] && stty "$stty_orig" | |
7280d581 KP |
190 | fi |
191 | } 9>/.console_lock | |
192 | ||
34eef3e9 DS |
193 | [ "$ret" -ne 0 ] && echo "Wrong password" >&2 |
194 | return "$ret" | |
7280d581 | 195 | } |
245529d8 AZ |
196 | |
197 | # Parse root=, rootfstype=, return them decoded and normalised to zfs:AUTO for auto, plain dset for explicit | |
198 | # | |
199 | # True if ZFS-on-root, false if we shouldn't | |
200 | # | |
201 | # Supported values: | |
202 | # root= | |
203 | # root=zfs | |
204 | # root=zfs: | |
205 | # root=zfs:AUTO | |
206 | # | |
207 | # root=ZFS=data/set | |
208 | # root=zfs:data/set | |
209 | # root=zfs:ZFS=data/set (as a side-effect; allowed but undocumented) | |
210 | # | |
211 | # rootfstype=zfs AND root=data/set <=> root=data/set | |
212 | # rootfstype=zfs AND root= <=> root=zfs:AUTO | |
213 | # | |
214 | # '+'es in explicit dataset decoded to ' 's. | |
215 | decode_root_args() { | |
216 | if [ -n "$rootfstype" ]; then | |
217 | [ "$rootfstype" = zfs ] | |
218 | return | |
219 | fi | |
220 | ||
221 | root=$(getarg root=) | |
222 | rootfstype=$(getarg rootfstype=) | |
223 | ||
224 | # shellcheck disable=SC2249 | |
225 | case "$root" in | |
226 | ""|zfs|zfs:|zfs:AUTO) | |
227 | root=zfs:AUTO | |
228 | rootfstype=zfs | |
229 | return 0 | |
230 | ;; | |
231 | ||
232 | ZFS=*|zfs:*) | |
233 | root="${root#zfs:}" | |
234 | root="${root#ZFS=}" | |
235 | root=$(echo "$root" | tr '+' ' ') | |
236 | rootfstype=zfs | |
237 | return 0 | |
238 | ;; | |
239 | esac | |
240 | ||
241 | if [ "$rootfstype" = "zfs" ]; then | |
242 | case "$root" in | |
243 | "") root=zfs:AUTO ;; | |
244 | *) root=$(echo "$root" | tr '+' ' ') ;; | |
245 | esac | |
246 | return 0 | |
247 | fi | |
248 | ||
249 | return 1 | |
250 | } |