diff --git a/contrib/dracut/90zfs/mount-zfs.sh.in b/contrib/dracut/90zfs/mount-zfs.sh.in index 5fd406231..5d02a8d74 100755 --- a/contrib/dracut/90zfs/mount-zfs.sh.in +++ b/contrib/dracut/90zfs/mount-zfs.sh.in @@ -20,6 +20,42 @@ fi info "ZFS: No sysroot.mount exists or zfs-generator did not extend it." info "ZFS: Mounting root with the traditional mount-zfs.sh instead." +# ask_for_password tries prompt cmd +# +# Wraps around plymouth ask-for-password and adds fallback to tty password ask +# if plymouth is not present. +ask_for_password() { + tries="$1" + prompt="$2" + cmd="$3" + + { + flock -s 9 + + # Prompt for password with plymouth, if installed and running. + if plymouth --ping 2>/dev/null; then + plymouth ask-for-password \ + --prompt "$prompt" --number-of-tries="$tries" | \ + eval "$cmd" + ret=$? + else + i=1 + while [ "$i" -le "$tries" ]; do + printf "%s [%i/%i]:" "$prompt" "$i" "$tries" >&2 + eval "$cmd" && ret=0 && break + ret=$? + i=$((i+1)) + printf '\n' >&2 + done + unset i + fi + } 9>/.console_lock + + [ "$ret" -ne 0 ] && echo "Wrong password" >&2 + return "$ret" +} + + # Delay until all required block devices are present. modprobe zfs 2>/dev/null udevadm settle @@ -45,31 +81,39 @@ fi ZFS_DATASET="${ZFS_DATASET:-${root}}" ZFS_POOL="${ZFS_DATASET%%/*}" -if import_pool "${ZFS_POOL}" ; then - # Load keys if we can or if we need to - if [ "$(zpool list -H -o feature@encryption "${ZFS_POOL}")" = 'active' ]; then - # if the root dataset has encryption enabled - ENCRYPTIONROOT="$(zfs get -H -o value encryptionroot "${ZFS_DATASET}")" - if ! [ "${ENCRYPTIONROOT}" = "-" ]; then - KEYSTATUS="$(zfs get -H -o value keystatus "${ENCRYPTIONROOT}")" - # if the key needs to be loaded - if [ "$KEYSTATUS" = "unavailable" ]; then - # decrypt them - ask_for_password \ - 5 \ - "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \ - "zfs load-key '${ENCRYPTIONROOT}'" - fi + +if ! zpool get -Ho name "${ZFS_POOL}" > /dev/null 2>&1; then + info "ZFS: Importing pool ${ZFS_POOL}..." + # shellcheck disable=SC2086 + if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${ZFS_POOL}"; then + warn "ZFS: Unable to import pool ${ZFS_POOL}" + rootok=0 + return 1 + fi +fi + +# Load keys if we can or if we need to +if [ "$(zpool get -Ho value feature@encryption "${ZFS_POOL}")" = 'active' ]; then + # if the root dataset has encryption enabled + ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${ZFS_DATASET}")" + if ! [ "${ENCRYPTIONROOT}" = "-" ]; then + KEYSTATUS="$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" + # if the key needs to be loaded + if [ "$KEYSTATUS" = "unavailable" ]; then + # decrypt them + ask_for_password \ + 5 \ + "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \ + "zfs load-key '${ENCRYPTIONROOT}'" fi fi - # Let us tell the initrd to run on shutdown. - # We have a shutdown hook to run - # because we imported the pool. - info "ZFS: Mounting dataset ${ZFS_DATASET}..." - if mount_dataset "${ZFS_DATASET}" ; then - ROOTFS_MOUNTED=yes - return 0 - fi fi -rootok=0 +# Let us tell the initrd to run on shutdown. +# We have a shutdown hook to run +# because we imported the pool. +info "ZFS: Mounting dataset ${ZFS_DATASET}..." +if ! mount_dataset "${ZFS_DATASET}"; then + rootok=0 + return 1 +fi diff --git a/contrib/dracut/90zfs/zfs-lib.sh.in b/contrib/dracut/90zfs/zfs-lib.sh.in index 6643e1bb3..a8903a5e1 100755 --- a/contrib/dracut/90zfs/zfs-lib.sh.in +++ b/contrib/dracut/90zfs/zfs-lib.sh.in @@ -1,4 +1,5 @@ #!/bin/sh +# shellcheck disable=SC2034 command -v getarg >/dev/null || . /lib/dracut-lib.sh || . /usr/lib/dracut/modules.d/99base/dracut-lib.sh command -v getargbool >/dev/null || { @@ -16,34 +17,14 @@ command -v getargbool >/dev/null || { } } -OLDIFS="${IFS}" -NEWLINE=" -" TAB=" " -ZPOOL_IMPORT_OPTS="" -if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then +ZPOOL_IMPORT_OPTS= +if getargbool 0 zfs_force -y zfs.force -y zfsforce; then warn "ZFS: Will force-import pools if necessary." - ZPOOL_IMPORT_OPTS="${ZPOOL_IMPORT_OPTS} -f" + ZPOOL_IMPORT_OPTS=-f fi -# import_pool POOL -# imports the given zfs pool if it isn't imported already. -import_pool() { - pool="${1}" - - if ! zpool list -H "${pool}" > /dev/null 2>&1; then - info "ZFS: Importing pool ${pool}..." - # shellcheck disable=SC2086 - if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${pool}" ; then - warn "ZFS: Unable to import pool ${pool}" - return 1 - fi - fi - - return 0 -} - _mount_dataset_cb() { # shellcheck disable=SC2154 mount -o zfsutil -t zfs "${1}" "${NEWROOT}${2}" @@ -97,41 +78,6 @@ for_relevant_root_children() { ) } -# ask_for_password tries prompt cmd -# -# Wraps around plymouth ask-for-password and adds fallback to tty password ask -# if plymouth is not present. -ask_for_password() { - tries="$1" - prompt="$2" - cmd="$3" - - { - flock -s 9 - - # Prompt for password with plymouth, if installed and running. - if plymouth --ping 2>/dev/null; then - plymouth ask-for-password \ - --prompt "$prompt" --number-of-tries="$tries" | \ - eval "$cmd" - ret=$? - else - i=1 - while [ "$i" -le "$tries" ]; do - printf "%s [%i/%i]:" "$prompt" "$i" "$tries" >&2 - eval "$cmd" && ret=0 && break - ret=$? - i=$((i+1)) - printf '\n' >&2 - done - unset i - fi - } 9>/.console_lock - - [ "$ret" -ne 0 ] && echo "Wrong password" >&2 - return "$ret" -} - # Parse root=, rootfstype=, return them decoded and normalised to zfs:AUTO for auto, plain dset for explicit # # True if ZFS-on-root, false if we shouldn't