diff --git a/contrib/dracut/90zfs/export-zfs.sh.in b/contrib/dracut/90zfs/export-zfs.sh.in index 6b711a0d151b..cfe059479436 100755 --- a/contrib/dracut/90zfs/export-zfs.sh.in +++ b/contrib/dracut/90zfs/export-zfs.sh.in @@ -1,24 +1,22 @@ #!/bin/sh -. /lib/dracut-zfs-lib.sh - _do_zpool_export() { info "ZFS: Exporting ZFS storage pools..." - errs=$(export_all -F 2>&1) + errs=$(zpool export -aF 2>&1) ret=$? echo "${errs}" | vwarn if [ "${ret}" -ne 0 ]; then info "ZFS: There was a problem exporting pools." fi if [ -n "$1" ]; then info "ZFS: pool list" zpool list 2>&1 | vinfo fi return "$ret" } if command -v zpool >/dev/null; then _do_zpool_export "${1}" fi diff --git a/contrib/dracut/90zfs/mount-zfs.sh.in b/contrib/dracut/90zfs/mount-zfs.sh.in index 68e3f0e0d60b..7e11c9afdaee 100755 --- a/contrib/dracut/90zfs/mount-zfs.sh.in +++ b/contrib/dracut/90zfs/mount-zfs.sh.in @@ -1,86 +1,86 @@ #!/bin/sh # shellcheck disable=SC2034,SC2154 . /lib/dracut-zfs-lib.sh ZFS_DATASET="" ZFS_POOL="" case "${root}" in zfs:*) ;; *) return ;; esac GENERATOR_FILE=/run/systemd/generator/sysroot.mount GENERATOR_EXTENSION=/run/systemd/generator/sysroot.mount.d/zfs-enhancement.conf if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ] ; then # If the ZFS sysroot.mount flag exists, the initial RAM disk configured # it to mount ZFS on root. In that case, we bail early. This flag # file gets created by the zfs-generator program upon successful run. info "ZFS: There is a sysroot.mount and zfs-generator has extended it." info "ZFS: Delegating root mount to sysroot.mount." # Let us tell the initrd to run on shutdown. # We have a shutdown hook to run # because we imported the pool. # We now prevent Dracut from running this thing again. for zfsmounthook in "$hookdir"/mount/*zfs* ; do if [ -f "$zfsmounthook" ] ; then rm -f "$zfsmounthook" fi done return 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." # Delay until all required block devices are present. modprobe zfs 2>/dev/null udevadm settle if [ "${root}" = "zfs:AUTO" ] ; then if ! ZFS_DATASET="$(find_bootfs)" ; then # shellcheck disable=SC2086 zpool import -N -a ${ZPOOL_IMPORT_OPTS} if ! ZFS_DATASET="$(find_bootfs)" ; then warn "ZFS: No bootfs attribute found in importable pools." - export_all -F + zpool export -aF rootok=0 return 1 fi fi info "ZFS: Using ${ZFS_DATASET} as root." fi ZFS_DATASET="${ZFS_DATASET:-${root#zfs:}}" 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 \ --tries 5 \ --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \ --cmd "zfs load-key '${ENCRYPTIONROOT}'" fi 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 diff --git a/contrib/dracut/90zfs/zfs-lib.sh.in b/contrib/dracut/90zfs/zfs-lib.sh.in index d7c3e96c1213..afd872d69d58 100755 --- a/contrib/dracut/90zfs/zfs-lib.sh.in +++ b/contrib/dracut/90zfs/zfs-lib.sh.in @@ -1,209 +1,193 @@ #!/bin/sh command -v getarg >/dev/null || . /lib/dracut-lib.sh command -v getargbool >/dev/null || { # Compatibility with older Dracut versions. # With apologies to the Dracut developers. getargbool() { _default="$1"; shift ! _b=$(getarg "$@") && [ -z "$_b" ] && _b="$_default" if [ -n "$_b" ]; then [ "$_b" = "0" ] && return 1 [ "$_b" = "no" ] && return 1 [ "$_b" = "off" ] && return 1 fi return 0 } } OLDIFS="${IFS}" NEWLINE=" " TAB=" " 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" fi # find_bootfs # returns the first dataset with the bootfs attribute. find_bootfs() { IFS="${NEWLINE}" for dataset in $(zpool list -H -o bootfs); do case "${dataset}" in "" | "-") continue ;; "no pools available") IFS="${OLDIFS}" return 1 ;; *) IFS="${OLDIFS}" echo "${dataset}" return 0 ;; esac done IFS="${OLDIFS}" return 1 } # 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}" } # mount_dataset DATASET # mounts the given zfs dataset. mount_dataset() { dataset="${1}" mountpoint="$(zfs get -H -o value mountpoint "${dataset}")" ret=0 # We need zfsutil for non-legacy mounts and not for legacy mounts. if [ "${mountpoint}" = "legacy" ] ; then mount -t zfs "${dataset}" "${NEWROOT}" || ret=$? else mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}" || ret=$? if [ "$ret" = "0" ]; then for_relevant_root_children "${dataset}" _mount_dataset_cb || ret=$? fi fi return "${ret}" } # for_relevant_root_children DATASET EXEC # Runs "EXEC dataset mountpoint" for all children of DATASET that are needed for system bringup # Used by zfs-generator.sh and friends, too! for_relevant_root_children() { dataset="${1}" exec="${2}" zfs list -t filesystem -Ho name,mountpoint,canmount -r "${dataset}" | ( _ret=0 while IFS="${TAB}" read -r dataset mountpoint canmount; do [ "$canmount" != "on" ] && continue case "$mountpoint" in /etc|/bin|/lib|/lib??|/libx32|/usr) # 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 "${exec}" "${dataset}" "${mountpoint}" || _ret=$? ;; *) # Up to the real init to remount everything else it might need ;; esac done exit "${_ret}" ) } -# export_all OPTS -# exports all imported zfs pools. -export_all() { - ret=0 - - IFS="${NEWLINE}" - for pool in $(zpool list -H -o name) ; do - if zpool list -H "${pool}" > /dev/null 2>&1; then - zpool export "${pool}" "$@" || ret=$? - fi - done - IFS="${OLDIFS}" - - return "${ret}" -} - # ask_for_password # # Wraps around plymouth ask-for-password and adds fallback to tty password ask # if plymouth is not present. # # --cmd command # Command to execute. Required. # --prompt prompt # Password prompt. Note that function already adds ':' at the end. # Recommended. # --tries n # How many times repeat command on its failure. Default is 3. # --ply-[cmd|prompt|tries] # Command/prompt/tries specific for plymouth password ask only. # --tty-[cmd|prompt|tries] # Command/prompt/tries specific for tty password ask only. # --tty-echo-off # Turn off input echo before tty command is executed and turn on after. # It's useful when password is read from stdin. ask_for_password() { ply_tries=3 tty_tries=3 while [ "$#" -gt 0 ]; do case "$1" in --cmd) ply_cmd="$2"; tty_cmd="$2"; shift;; --ply-cmd) ply_cmd="$2"; shift;; --tty-cmd) tty_cmd="$2"; shift;; --prompt) ply_prompt="$2"; tty_prompt="$2"; shift;; --ply-prompt) ply_prompt="$2"; shift;; --tty-prompt) tty_prompt="$2"; shift;; --tries) ply_tries="$2"; tty_tries="$2"; shift;; --ply-tries) ply_tries="$2"; shift;; --tty-tries) tty_tries="$2"; shift;; --tty-echo-off) tty_echo_off=yes;; *) echo "ask_for_password(): wrong opt '$1'" >&2;; esac shift done { flock -s 9; # Prompt for password with plymouth, if installed and running. if plymouth --ping 2>/dev/null; then plymouth ask-for-password \ --prompt "$ply_prompt" --number-of-tries="$ply_tries" | \ eval "$ply_cmd" ret=$? else if [ "$tty_echo_off" = yes ]; then stty_orig="$(stty -g)" stty -echo fi i=1 while [ "$i" -le "$tty_tries" ]; do [ -n "$tty_prompt" ] && \ printf "%s [%i/%i]:" "$tty_prompt" "$i" "$tty_tries" >&2 eval "$tty_cmd" && ret=0 && break ret=$? i=$((i+1)) [ -n "$tty_prompt" ] && printf '\n' >&2 done unset i [ "$tty_echo_off" = yes ] && stty "$stty_orig" fi } 9>/.console_lock [ "$ret" -ne 0 ] && echo "Wrong password" >&2 return "$ret" }