Skip to content

Commit 075cba0

Browse files
committed
zfsbootmenu: add zbm.waitfor argument handler
With keyfiles being stored on USB drives, the boot process can be non-deterministic due to intermittently missing /dev entries. Users can now provide one or more devices that must be present before the pool import process can start. Unlike dracut, you can simply hit the escape key to cancel this check.
1 parent ad127f3 commit 075cba0

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed

docs/man/zfsbootmenu.7.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ These options are set on the kernel command line when booting the initramfs or U
143143

144144
Enable automatic font resizing of the kernel console to normalize the apparent resolution for both low resolution and high resolution displays. This option is enabled by default.
145145

146+
**zbm.waitfor=device,device,...**
147+
148+
Ensure that one or more devices are present before starting the pool import process. Devices may be specified as full paths to device nodes (*e.g.*, **/dev/sda** or **/dev/disk/by-id/wwn-0x500a07510ee65912**) or, for convenience, as a typed indicator of the form **TYPE=VALUE**, which will be expanded internally as
149+
150+
**/dev/disk/by-TYPE/VALUE**
151+
152+
The use of full device paths other than descendants of **/dev/disk/** is fragile and should be avoided.
153+
146154
Deprecated Parameters
147155
---------------------
148156

zfsbootmenu/libexec/zfsbootmenu-init

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,60 @@ elif [ ! -e /etc/hostid ]; then
7878
write_hostid "${default_hostid}"
7979
fi
8080

81+
# Wait for devices to show up
82+
83+
if [ -n "${zbm_waitfor_devices}" ]; then
84+
IFS=',' read -r -a user_devices <<<"${zbm_waitfor_devices}"
85+
while true; do
86+
FOUND=0
87+
EXPECTED=0
88+
missing=()
89+
90+
for device in "${user_devices[@]}"; do
91+
case "${device}" in
92+
/dev/*)
93+
((EXPECTED=EXPECTED+1))
94+
if [ -e "${device}" ] ; then
95+
((FOUND=FOUND+1))
96+
else
97+
missing+=( "$device" )
98+
fi
99+
;;
100+
*=*)
101+
((EXPECTED=EXPECTED+1))
102+
path_prefix="/dev/disk/by-${device%=*}"
103+
checkfor="${path_prefix,,}/${device##*=}"
104+
if [ -e "${checkfor}" ] ; then
105+
((FOUND=FOUND+1))
106+
else
107+
missing+=( "$device" )
108+
fi
109+
;;
110+
*)
111+
zerror "malformed device: '${device}'"
112+
;;
113+
esac
114+
done
115+
116+
if [ ${FOUND} -eq ${EXPECTED} ]; then
117+
break
118+
else
119+
if ! timed_prompt -d 3 -e "to cancel" \
120+
-m "" \
121+
-m "$( colorize red "One or more required devices are missing" )" \
122+
-p "retrying in $( colorize yellow "%0.2d" ) seconds" ; then
123+
for dev in "${missing[@]}" ; do
124+
zerror "required device '${dev}' not found"
125+
done
126+
127+
break
128+
fi
129+
fi
130+
done
131+
132+
unset FOUND EXPECTED device path_prefix checkfor
133+
fi
134+
81135
# Import ZBM hooks from an external root, if they exist
82136
if [ -n "${zbm_hook_root}" ]; then
83137
import_zbm_hooks "${zbm_hook_root}"

zfsbootmenu/pre-init/zfsbootmenu-parse-commandline.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ if zbm_prefer_pool=$( get_zbm_arg zbm.prefer ) ; then
226226
zinfo "preferring ${zbm_prefer_pool} for bootfs"
227227
fi
228228

229+
zbm_waitfor_devices=
230+
if zbm_waitfor_devices=$( get_zbm_arg zbm.waitfor ) ; then
231+
zinfo "system will wait for ${zbm_waitfor_devices}"
232+
fi
233+
229234
# pool! : this pool must be imported before all others
230235
# pool!!: this pool, and no others, must be imported
231236

zfsbootmenu/pre-init/zfsbootmenu-preinit.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export zbm_sort='${zbm_sort}'
3333
export zbm_set_hostid='${zbm_set_hostid}'
3434
export zbm_import_delay='${zbm_import_delay}'
3535
export zbm_hook_root='${zbm_hook_root}'
36+
export zbm_waitfor_devices='${zbm_waitfor_devices}'
3637
export control_term='${control_term}'
3738
# END additions by zfsbootmenu-preinit.sh
3839
EOF

0 commit comments

Comments
 (0)