diff --git a/contrib/dracut/90zfs/Makefile.am b/contrib/dracut/90zfs/Makefile.am index 3f7050300994..5a68e01f05c3 100644 --- a/contrib/dracut/90zfs/Makefile.am +++ b/contrib/dracut/90zfs/Makefile.am @@ -1,24 +1,25 @@ include $(top_srcdir)/config/Substfiles.am include $(top_srcdir)/config/Shellcheck.am pkgdracutdir = $(dracutdir)/modules.d/90zfs pkgdracut_SCRIPTS = \ export-zfs.sh \ module-setup.sh \ mount-zfs.sh \ parse-zfs.sh \ zfs-generator.sh \ zfs-load-key.sh \ zfs-needshutdown.sh \ zfs-lib.sh \ import-opts-generator.sh pkgdracut_DATA = \ zfs-env-bootfs.service \ + zfs-nonroot-necessities.service \ zfs-snapshot-bootfs.service \ zfs-rollback-bootfs.service SUBSTFILES += $(pkgdracut_SCRIPTS) $(pkgdracut_DATA) # Provided by /bin/sleep, and, again, every implementation of that supports this CHECKBASHISMS_IGNORE = -e 'sleep only takes one integer' -e 'sleep 0.' diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in index 4ac302de507c..a247e2ad2e94 100755 --- a/contrib/dracut/90zfs/module-setup.sh.in +++ b/contrib/dracut/90zfs/module-setup.sh.in @@ -1,113 +1,116 @@ #!/usr/bin/env bash # shellcheck disable=SC2154 check() { # We depend on udev-rules being loaded [ "${1}" = "-d" ] && return 0 # Verify the zfs tool chain for tool in "zgenhostid" "zpool" "zfs" "mount.zfs"; do command -v "${tool}" >/dev/null || return 1 done return 0 } depends() { echo udev-rules return 0 } installkernel() { instmods -c zfs } install() { inst_rules 90-zfs.rules 69-vdev.rules 60-zvol.rules inst_multiple \ zgenhostid \ zfs \ zpool \ mount.zfs \ hostid \ grep \ awk \ tr \ cut \ head || { dfatal "Failed to install essential binaries"; exit 1; } # Adapted from https://github.com/zbm-dev/zfsbootmenu if ! ldd "$(command -v zpool)" | grep -qF 'libgcc_s.so'; then # On systems with gcc-config (Gentoo, Funtoo, etc.), use it to find libgcc_s if command -v gcc-config >/dev/null; then inst_simple "/usr/lib/gcc/$(s=$(gcc-config -c); echo "${s%-*}/${s##*-}")/libgcc_s.so.1" || { dfatal "Unable to install libgcc_s.so"; exit 1; } # Otherwise, use dracut's library installation function to find the right one elif ! inst_libdir_file "libgcc_s.so*"; then # If all else fails, just try looking for some gcc arch directory inst_simple /usr/lib/gcc/*/*/libgcc_s.so* || { dfatal "Unable to install libgcc_s.so"; exit 1; } fi fi inst_hook cmdline 95 "${moddir}/parse-zfs.sh" if [ -n "${systemdutildir}" ]; then inst_script "${moddir}/zfs-generator.sh" "${systemdutildir}/system-generators/dracut-zfs-generator" fi inst_hook pre-mount 90 "${moddir}/zfs-load-key.sh" inst_hook mount 98 "${moddir}/mount-zfs.sh" inst_hook cleanup 99 "${moddir}/zfs-needshutdown.sh" inst_hook shutdown 20 "${moddir}/export-zfs.sh" inst_script "${moddir}/zfs-lib.sh" "/lib/dracut-zfs-lib.sh" # -H ensures they are marked host-only # -o ensures there is no error upon absence of these files inst_multiple -o -H \ "@sysconfdir@/zfs/zpool.cache" \ "@sysconfdir@/zfs/vdev_id.conf" # Synchronize initramfs and system hostid if ! inst_simple -H @sysconfdir@/hostid; then if HOSTID="$(hostid 2>/dev/null)" && [ "${HOSTID}" != "00000000" ]; then zgenhostid -o "${initdir}@sysconfdir@/hostid" "${HOSTID}" mark_hostonly @sysconfdir@/hostid fi fi if dracut_module_included "systemd"; then inst_simple "${systemdsystemunitdir}/zfs-import.target" systemctl -q --root "${initdir}" add-wants initrd.target zfs-import.target inst_simple "${moddir}/zfs-env-bootfs.service" "${systemdsystemunitdir}/zfs-env-bootfs.service" systemctl -q --root "${initdir}" add-wants zfs-import.target zfs-env-bootfs.service + inst_simple "${moddir}/zfs-nonroot-necessities.service" "${systemdsystemunitdir}/zfs-nonroot-necessities.service" + systemctl -q --root "${initdir}" add-requires initrd-root-fs.target zfs-nonroot-necessities.service + for _service in \ "zfs-import-scan.service" \ "zfs-import-cache.service"; do inst_simple "${systemdsystemunitdir}/${_service}" systemctl -q --root "${initdir}" add-wants zfs-import.target "${_service}" # Add user-provided unit overrides # - /etc/systemd/system/zfs-import-{scan,cache}.service # - /etc/systemd/system/zfs-import-{scan,cache}.service.d/overrides.conf # -H ensures they are marked host-only # -o ensures there is no error upon absence of these files inst_multiple -o -H \ "${systemdsystemconfdir}/${_service}" \ "${systemdsystemconfdir}/${_service}.d/"*.conf done for _service in \ "zfs-snapshot-bootfs.service" \ "zfs-rollback-bootfs.service"; do inst_simple "${moddir}/${_service}" "${systemdsystemunitdir}/${_service}" systemctl -q --root "${initdir}" add-wants initrd.target "${_service}" done inst_simple "${moddir}/import-opts-generator.sh" "${systemdutildir}/system-environment-generators/zfs-import-opts.sh" fi } diff --git a/contrib/dracut/90zfs/zfs-env-bootfs.service.in b/contrib/dracut/90zfs/zfs-env-bootfs.service.in index 34c88037cac2..7ebab4c1a58d 100644 --- a/contrib/dracut/90zfs/zfs-env-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-env-bootfs.service.in @@ -1,14 +1,23 @@ [Unit] -Description=Set BOOTFS environment for dracut -Documentation=man:zpool(8) +Description=Set BOOTFS and BOOTFSFLAGS environment variables for dracut DefaultDependencies=no After=zfs-import-cache.service After=zfs-import-scan.service Before=zfs-import.target [Service] Type=oneshot -ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)" +ExecStart=/bin/sh -c ' \ + . /lib/dracut-zfs-lib.sh; \ + decode_root_args || exit 0; \ + [ "$root" = "zfs:AUTO" ] && root="$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)"; \ + rootflags="$(getarg rootflags=)"; \ + case ",$rootflags," in \ + *,zfsutil,*) ;; \ + ,,) rootflags=zfsutil ;; \ + *) rootflags="zfsutil,$rootflags" ;; \ + esac; \ + exec systemctl set-environment BOOTFS="$root" BOOTFSFLAGS="$rootflags"' [Install] WantedBy=zfs-import.target diff --git a/contrib/dracut/90zfs/zfs-generator.sh.in b/contrib/dracut/90zfs/zfs-generator.sh.in index 56f7ca9785ba..4e1eb7490e0d 100755 --- a/contrib/dracut/90zfs/zfs-generator.sh.in +++ b/contrib/dracut/90zfs/zfs-generator.sh.in @@ -1,99 +1,42 @@ #!/bin/sh # shellcheck disable=SC2016,SC1004,SC2154 grep -wq debug /proc/cmdline && debug=1 [ -n "$debug" ] && echo "zfs-generator: starting" >> /dev/kmsg GENERATOR_DIR="$1" [ -n "$GENERATOR_DIR" ] || { echo "zfs-generator: no generator directory specified, exiting" >> /dev/kmsg exit 1 } # shellcheck source=zfs-lib.sh.in . /lib/dracut-zfs-lib.sh decode_root_args || exit 0 -[ -z "${rootflags}" ] && rootflags=$(getarg rootflags=) -case ",${rootflags}," in - *,zfsutil,*) ;; - ,,) rootflags=zfsutil ;; - *) rootflags="zfsutil,${rootflags}" ;; -esac - [ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg -mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/initrd-root-fs.target.requires "$GENERATOR_DIR"/dracut-pre-mount.service.d +mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/dracut-pre-mount.service.d + { echo "[Unit]" echo "Before=initrd-root-fs.target" echo "After=zfs-import.target" echo echo "[Mount]" - if [ "${root}" = "zfs:AUTO" ]; then - echo "PassEnvironment=BOOTFS" - echo 'What=${BOOTFS}' - else - echo "What=${root}" - fi + echo "PassEnvironment=BOOTFS BOOTFSFLAGS" + echo 'What=${BOOTFS}' echo "Type=zfs" - echo "Options=${rootflags}" + echo 'Options=${BOOTFSFLAGS}' } > "$GENERATOR_DIR"/sysroot.mount.d/zfs-enhancement.conf ln -fs ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount - -if [ "${root}" = "zfs:AUTO" ]; then - { - echo "[Unit]" - echo "Before=initrd-root-fs.target" - echo "After=sysroot.mount" - echo "DefaultDependencies=no" - echo - echo "[Service]" - echo "Type=oneshot" - echo "PassEnvironment=BOOTFS" - echo "ExecStart=/bin/sh -c '" ' \ - . /lib/dracut-zfs-lib.sh; \ - _zfs_nonroot_necessities_cb() { \ - zfs mount | grep -m1 -q "^$1 " && return 0; \ - echo "Mounting $1 on /sysroot$2"; \ - mount -o zfsutil -t zfs "$1" "/sysroot$2"; \ - }; \ - for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb;' \ - "'" - } > "$GENERATOR_DIR"/zfs-nonroot-necessities.service - ln -fs ../zfs-nonroot-necessities.service "$GENERATOR_DIR"/initrd-root-fs.target.requires/zfs-nonroot-necessities.service -else - # We can solve this statically at generation time, so do! - _zfs_generator_cb() { - dset="${1}" - mpnt="${2}" - unit="$(systemd-escape --suffix=mount -p "/sysroot${mpnt}")" - - { - echo "[Unit]" - echo "Before=initrd-root-fs.target" - echo "After=sysroot.mount" - echo - echo "[Mount]" - echo "Where=/sysroot${mpnt}" - echo "What=${dset}" - echo "Type=zfs" - echo "Options=zfsutil" - } > "$GENERATOR_DIR/${unit}" - ln -fs ../"${unit}" "$GENERATOR_DIR"/initrd-root-fs.target.requires/"${unit}" - } - - for_relevant_root_children "${root}" _zfs_generator_cb -fi - - { echo "[Unit]" echo "After=zfs-import.target" } > "$GENERATOR_DIR"/dracut-pre-mount.service.d/zfs-enhancement.conf [ -n "$debug" ] && echo "zfs-generator: finished" >> /dev/kmsg exit 0 diff --git a/contrib/dracut/90zfs/zfs-lib.sh.in b/contrib/dracut/90zfs/zfs-lib.sh.in index a91b56ba7f3c..171616bce072 100755 --- a/contrib/dracut/90zfs/zfs-lib.sh.in +++ b/contrib/dracut/90zfs/zfs-lib.sh.in @@ -1,119 +1,119 @@ #!/bin/sh # shellcheck disable=SC2034 command -v getarg >/dev/null || . /lib/dracut-lib.sh || . /usr/lib/dracut/modules.d/99base/dracut-lib.sh 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=-f fi _mount_dataset_cb() { 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! +# Used by zfs-nonroot-necessities.service 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} ) } # 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 # # Supported values: # root= # root=zfs # root=zfs: # root=zfs:AUTO # # root=ZFS=data/set # root=zfs:data/set # root=zfs:ZFS=data/set (as a side-effect; allowed but undocumented) # # rootfstype=zfs AND root=data/set <=> root=data/set # rootfstype=zfs AND root= <=> root=zfs:AUTO # # '+'es in explicit dataset decoded to ' 's. decode_root_args() { if [ -n "$rootfstype" ]; then [ "$rootfstype" = zfs ] return fi root=$(getarg root=) rootfstype=$(getarg rootfstype=) # shellcheck disable=SC2249 case "$root" in ""|zfs|zfs:|zfs:AUTO) root=zfs:AUTO rootfstype=zfs return 0 ;; ZFS=*|zfs:*) root="${root#zfs:}" root="${root#ZFS=}" root=$(echo "$root" | tr '+' ' ') rootfstype=zfs return 0 ;; esac if [ "$rootfstype" = "zfs" ]; then case "$root" in "") root=zfs:AUTO ;; *) root=$(echo "$root" | tr '+' ' ') ;; esac return 0 fi return 1 } diff --git a/contrib/dracut/90zfs/zfs-nonroot-necessities.service.in b/contrib/dracut/90zfs/zfs-nonroot-necessities.service.in new file mode 100644 index 000000000000..8f420c737c72 --- /dev/null +++ b/contrib/dracut/90zfs/zfs-nonroot-necessities.service.in @@ -0,0 +1,20 @@ +[Unit] +Before=initrd-root-fs.target +After=sysroot.mount +DefaultDependencies=no +ConditionEnvironment=BOOTFS + +[Service] +Type=oneshot +PassEnvironment=BOOTFS +ExecStart=/bin/sh -c ' \ + . /lib/dracut-zfs-lib.sh; \ + _zfs_nonroot_necessities_cb() { \ + @sbindir@/zfs mount | grep -m1 -q "^$1 " && return 0; \ + echo "Mounting $1 on /sysroot$2"; \ + mount -o zfsutil -t zfs "$1" "/sysroot$2"; \ + }; \ + for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb' + +[Install] +RequiredBy=initrd-root-fs.target diff --git a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in index a29cf3a3dd81..68fdcb1f323e 100644 --- a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in @@ -1,12 +1,13 @@ [Unit] Description=Rollback bootfs just before it is mounted Requisite=zfs-import.target After=zfs-import.target dracut-pre-mount.service zfs-snapshot-bootfs.service Before=dracut-mount.service DefaultDependencies=no ConditionKernelCommandLine=bootfs.rollback +ConditionEnvironment=BOOTFS [Service] Type=oneshot -ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$root@${SNAPNAME:-%v}"' +ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$BOOTFS@${SNAPNAME:-%v}"' RemainAfterExit=yes diff --git a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in index 9e73d1a78724..a675b5b2ea98 100644 --- a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in @@ -1,12 +1,13 @@ [Unit] Description=Snapshot bootfs just before it is mounted Requisite=zfs-import.target After=zfs-import.target dracut-pre-mount.service Before=dracut-mount.service DefaultDependencies=no ConditionKernelCommandLine=bootfs.snapshot +ConditionEnvironment=BOOTFS [Service] Type=oneshot -ExecStart=-/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"' +ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$BOOTFS@${SNAPNAME:-%v}"' RemainAfterExit=yes diff --git a/man/man7/dracut.zfs.7 b/man/man7/dracut.zfs.7 index 0f446fe2fe3f..d9234bdf5649 100644 --- a/man/man7/dracut.zfs.7 +++ b/man/man7/dracut.zfs.7 @@ -1,278 +1,278 @@ .\" SPDX-License-Identifier: 0BSD .\" -.Dd April 4, 2022 +.Dd March 28, 2023 .Dt DRACUT.ZFS 7 .Os . .Sh NAME .Nm dracut.zfs .Nd overview of ZFS dracut hooks . .Sh SYNOPSIS .Bd -literal -compact parse-zfs.sh \(-> dracut-cmdline.service | \(da | … | \(da \e\(em\(em\(em\(em\(em\(em\(em\(em\(-> dracut-initqueue.service | zfs-import-opts.sh zfs-load-module.service \(da | | | | sysinit.target \(da | \(da | | zfs-import-scan.service \(da zfs-import-scan.service \(da \(da | zfs-import-cache.service | zfs-import-cache.service basic.target | | \e__________________| | \(da \(da \(da | zfs-load-key.sh zfs-env-bootfs.service | | \(da \(da \(da zfs-import.target \(-> dracut-pre-mount.service | \(ua | | dracut-zfs-generator | - | ____________________/| + | _____________________/| |/ \(da - | sysroot.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em dracut-zfs-generator - | | \(da | - | \(da sysroot-{usr,etc,lib,&c.}.mount | - | initrd-root-fs.target \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em or \(da - | | zfs-nonroot-necessities.service + | sysroot.mount \(<-\(em\(em\(em dracut-zfs-generator + | | + | \(da + | initrd-root-fs.target \(<-\(em zfs-nonroot-necessities.service + | | | | \(da | \(da dracut-mount.service | zfs-snapshot-bootfs.service | | | \(da | \(da … | zfs-rollback-bootfs.service | | | \(da | - | sysroot-usr.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/ + | /sysroot/{usr,etc,lib,&c.} \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/ | | | \(da | initrd-fs.target \e______________________ | \e| \(da export-zfs.sh initrd.target | | \(da \(da dracut-shutdown.service … | \(da zfs-needshutdown.sh \(-> initrd-cleanup.service .Ed .Pp Compare .Xr dracut.bootup 7 for the full flowchart. . .Sh DESCRIPTION Under dracut, booting with .No ZFS-on- Ns Pa / is facilitated by a number of hooks in the .Nm 90zfs module. .Pp Booting into a ZFS dataset requires .Sy mountpoint Ns = Ns Pa / to be set on the dataset containing the root filesystem (henceforth "the boot dataset") and at the very least either the .Sy bootfs property to be set to that dataset, or the .Sy root= kernel cmdline (or dracut drop-in) argument to specify it. .Pp All children of the boot dataset with .Sy canmount Ns = Ns Sy on with .Sy mountpoint Ns s matching .Pa /etc , /bin , /lib , /lib?? , /libx32 , No and Pa /usr globs are deemed essential and will be mounted as well. .Pp .Xr zfs-mount-generator 8 is recommended for proper functioning of the system afterward (correct mount properties, remounting, &c.). . .Sh CMDLINE .Ss Standard .Bl -tag -compact -width ".Sy root=zfs:AUTO , root=zfs: , root=zfs , Op Sy root=" .It Sy root=zfs:\& Ns Ar dataset , Sy root=ZFS= Ns Ar dataset Use .Ar dataset as the boot dataset. All pluses .Pq Sq + are replaced with spaces .Pq Sq \ . . .It Sy root=zfs:AUTO , root=zfs:\& , root=zfs , Op Sy root= After import, search for the first pool with the .Sy bootfs property set, use its value as-if specified as the .Ar dataset above. . .It Sy rootfstype=zfs root= Ns Ar dataset Equivalent to .Sy root=zfs:\& Ns Ar dataset . . .It Sy rootfstype=zfs Op Sy root= Equivalent to .Sy root=zfs:AUTO . . .It Sy rootflags= Ns Ar flags Mount the boot dataset with .Fl o Ar flags ; cf.\& .Sx Temporary Mount Point Properties in .Xr zfsprops 7 . These properties will not last, since all filesystems will be re-mounted from the real root. . .It Sy debug If specified, .Nm dracut-zfs-generator logs to the journal. .El .Pp Be careful about setting neither .Sy rootfstype=zfs nor .Sy root=zfs:\& Ns Ar dataset \(em other automatic boot selection methods, like .Nm systemd-gpt-auto-generator and .Nm systemd-fstab-generator might take precedent. . .Ss ZFS-specific .Bl -tag -compact -width ".Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name" .It Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name Execute .Nm zfs Cm snapshot Ar boot-dataset Ns Sy @ Ns Ar snapshot-name before pivoting to the real root. .Ar snapshot-name defaults to the current kernel release. . .It Sy bootfs.rollback Ns Op Sy = Ns Ar snapshot-name Execute .Nm zfs Cm snapshot Fl Rf Ar boot-dataset Ns Sy @ Ns Ar snapshot-name before pivoting to the real root. .Ar snapshot-name defaults to the current kernel release. . .It Sy spl_hostid= Ns Ar host-id Use .Xr zgenhostid 8 to set the host ID to .Ar host-id ; otherwise, .Pa /etc/hostid inherited from the real root is used. . .It Sy zfs_force , zfs.force , zfsforce Appends .Fl f to all .Nm zpool Cm import invocations; primarily useful in conjunction with .Sy spl_hostid= , or if no host ID was inherited. .El . .Sh FILES .Bl -tag -width 0 .It Pa parse-zfs.sh Pq Sy cmdline Processes .Sy spl_hostid= . If .Sy root= matches a known pattern, above, provides .Pa /dev/root and delays the initqueue until .Xr zfs 4 is loaded, . .It Pa zfs-import-opts.sh Pq Nm systemd No environment generator Turns .Sy zfs_force , zfs.force , No or Sy zfsforce into .Ev ZPOOL_IMPORT_OPTS Ns = Ns Fl f for .Pa zfs-import-scan.service or .Pa zfs-import-cache.service . . .It Pa zfs-load-key.sh Pq Sy pre-mount Loads encryption keys for the boot dataset and its essential descendants. .Bl -tag -compact -offset 4n -width ".Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL" .It Sy keylocation Ns = Ns Sy prompt Is prompted for via .Nm systemd-ask-password thrice. . .It Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL .Pa network-online.target is started before loading. . .It Sy keylocation Ns = Ns Sy file:// Ns Ar path If .Ar path doesn't exist, .Nm udevadm No is Cm settle Ns d . If it still doesn't, it's waited for for up to .Sy 10 Ns s . .El . .It Pa zfs-env-bootfs.service Pq Nm systemd No service After pool import, sets .Ev BOOTFS Ns = in the systemd environment to the first non-null .Sy bootfs value in iteration order. . .It Pa dracut-zfs-generator Pq Nm systemd No generator Generates .Pa sysroot.mount Pq using Sy rootflags= , No if any . If an explicit boot dataset was specified, also generates essential mountpoints .Pq Pa sysroot-etc.mount , sysroot-bin.mount , No &c.\& , otherwise generates .Pa zfs-nonroot-necessities.service which mounts them explicitly after .Pa /sysroot using .Ev BOOTFS Ns = . . .It Pa zfs-snapshot-bootfs.service , zfs-rollback-bootfs.service Pq Nm systemd No services Consume .Sy bootfs.snapshot and .Sy bootfs.rollback as described in .Sx CMDLINE . Use .Ev BOOTFS Ns = if no explicit boot dataset was specified. . .It Pa zfs-needshutdown.sh Pq Sy cleanup If any pools were imported, signals that shutdown hooks are required. . .It Pa export-zfs.sh Pq Sy shutdown Forcibly exports all pools. . .It Pa /etc/hostid , /etc/zfs/zpool.cache , /etc/zfs/vdev_id.conf Pq regular files Included verbatim, hostonly. . .It Pa mount-zfs.sh Pq Sy mount Does nothing on .Nm systemd systems .Pq if Pa dracut-zfs-generator No succeeded . Otherwise, loads encryption key for the boot dataset from the console or via plymouth. It may not work at all! .El . .Sh SEE ALSO .Xr dracut.bootup 7 , .Xr zfsprops 7 , .Xr zpoolprops 7 , .Xr dracut-shutdown.service 8 , .Xr systemd-fstab-generator 8 , .Xr systemd-gpt-auto-generator 8 , .Xr zfs-mount-generator 8 , .Xr zgenhostid 8