Skip to content

Commit

Permalink
Improved pool imports
Browse files Browse the repository at this point in the history
1. Allow `zbm.prefer=<pool>!` syntax for a *mandatory* preference; a
   mandatory poll must be imported before other pools will be attempted
   and ZBM continues.

2. Eliminate limits on import retries; the loop will continue
   indefinitely, displaying a countdown that the user can interrupt to
   drop to an emergency shell.
  • Loading branch information
ahesford committed Jun 26, 2021
1 parent a4f883b commit e2caa81
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 41 deletions.
47 changes: 18 additions & 29 deletions 90zfsbootmenu/zfsbootmenu-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,21 @@ else
boot_pool="${root}"
fi

# Do a dedicated pass for the preferred pool if one was provided
if [ -n "${boot_pool}" ]; then
first_pass=0
else
first_pass=1
fi

# If a boot pool is specified, that will be tried first
try_pool="${boot_pool}"
zbm_import_attempt=0
while true; do
if [ "${first_pass}" -eq 0 ]; then
# Try the preferred pool, exactly once
zdebug "attempting to import preferred pool ${boot_pool}"
try_pool="${boot_pool}"
else
try_pool=""
if [ -n "${try_pool}" ]; then
zdebug "attempting to import preferred pool ${try_pool}"
fi

first_pass=1

read_write='' import_pool "${try_pool}"

# shellcheck disable=SC2154
if check_for_pools; then
if [ -n "${try_pool}" ]; then
# If a single pool was requested and imported, try again for the others
# If a single pool was requested and imported, try importing others
try_pool=""
continue
else
# Otherwise, all possible pools were imported, nothing more to try
Expand All @@ -86,25 +76,24 @@ while true; do
# Store the hostid to use for for KCL overrides
echo -n "$spl_hostid" > "${BASE}/spl_hostid"

# Retry the cycle with a matched hostid
# If match_hostid succeeds, it has imported *a* pool;
# allow another pass to pick up others with the same hostid
try_pool=""
continue
elif [ -n "${try_pool}" ]; then
# Failure to import a specific pool is not an emergency;
# subsequent import passes try all other possible pools
elif [ -n "${try_pool}" ] && [ "${zbm_require_bpool:-0}" -ne 1 ]; then
# If a specific pool was tried unsuccessfully but is not a requirement,
# allow another pass to try any other importable pools
try_pool=""
continue
fi

if [ "${zbm_import_attempt}" -lt "${zbm_import_retries:-0}" ]; then
# The max number of import attempts has not been reached;
# retry unless the user decides to abort immediately
zbm_import_attempt="$((zbm_import_attempt + 1))"
zbm_import_attempt="$((zbm_import_attempt + 1))"
zinfo "unable to import a pool on attempt ${zbm_import_attempt}"

zinfo "pool import failed on attempt ${zbm_import_attempt} of ${zbm_import_retries}"

if delay="${zbm_import_delay:-5}" prompt="Unable to import pool, retrying in %0.2d seconds" \
timed_prompt "[RETURN] to retry immediately" "[ESCAPE] for a recovery shell"; then
# Just keep retrying after a delay until the user presses ESC
if delay="${zbm_import_delay:-5}" prompt="Unable to import pool, retrying in %0.2d seconds" \
timed_prompt "[RETURN] to retry immediately" "[ESCAPE] for a recovery shell"; then
continue
fi
fi

# Allow the user to attempt recovery
Expand Down
20 changes: 9 additions & 11 deletions 90zfsbootmenu/zfsbootmenu-parse-commandline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,10 @@ else
menu_timeout=10
fi

zbm_import_retries=$( getarg zbm.import_retries )
if [ "${zbm_import_retries:-0}" -gt 0 ] 2>/dev/null ; then
# Beyond logging, this validates that zbm_import_retries is a number
info "ZFSBootMenu: will attempt up to ${zbm_import_retries} import retries"
else
zbm_import_retries=0
fi

zbm_import_delay=$( getarg zbm.import_delay )
if [ "${zbm_import_delay:-0}" -gt 0 ] 2>/dev/null ; then
# Again, this validates that zbm_import_delay is numeric in addition to logging
if [ "${zbm_import_retries}" -gt 0 ]; then
info "ZFSBootMenu: import retry delay is ${zbm_import_delay} seconds"
fi
info "ZFSBootMenu: import retry delay is ${zbm_import_delay} seconds"
else
zbm_import_delay=5
fi
Expand Down Expand Up @@ -196,6 +186,14 @@ case "${root}" in
;;
esac

# Pool preference ending in ! indicates a hard requirement
bpool="${root%\!}"
if [ "${bpool}" != "${root}" ]; then
# shellcheck disable=SC2034
zbm_require_bpool=1
root="${bpool}"
fi

# Make sure Dracut is happy that we have a root
if [ ${wait_for_zfs} -eq 1 ]; then
ln -s /dev/null /dev/root 2>/dev/null
Expand Down
2 changes: 1 addition & 1 deletion 90zfsbootmenu/zfsbootmenu-preinit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ export import_policy="${import_policy}"
export menu_timeout="${menu_timeout}"
export loglevel="${loglevel}"
export root="${root}"
export zbm_require_bpool="${zbm_require_bpool}"
export zbm_sort="${zbm_sort}"
export zbm_set_hostid="${zbm_set_hostid}"
export zbm_import_delay="${zbm_import_delay}"
export zbm_import_retries="${zbm_import_retries}"
EOF

getcmdline > "${BASE}/zbm.cmdline"
Expand Down

0 comments on commit e2caa81

Please sign in to comment.