contrib; dracut: centralise root= parsing, actually support root=s
So far, everything parsed root= manually, which meant that while zfs-parse.sh was updated, and supposedly supported + -> ' ' conversion, it meant nothing Instead, centralise parsing, and allow: 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 So rootfstype=zfs /also/ behaves as expected, and + decoding works Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> Closes #13291
This commit is contained in:
parent
2c74617bcf
commit
245529d85f
|
@ -3,34 +3,20 @@
|
|||
|
||||
. /lib/dracut-zfs-lib.sh
|
||||
|
||||
ZFS_DATASET=""
|
||||
ZFS_POOL=""
|
||||
|
||||
case "${root}" in
|
||||
zfs:*) ;;
|
||||
*) return ;;
|
||||
esac
|
||||
decode_root_args || return 0
|
||||
|
||||
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.
|
||||
if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ]; then
|
||||
# We're under systemd and dracut-zfs-generator ran to completion.
|
||||
info "ZFS: Delegating root mount to sysroot.mount at al."
|
||||
|
||||
# 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
|
||||
rm -f "$hookdir"/mount/*zfs*
|
||||
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."
|
||||
|
||||
|
@ -38,6 +24,9 @@ info "ZFS: Mounting root with the traditional mount-zfs.sh instead."
|
|||
modprobe zfs 2>/dev/null
|
||||
udevadm settle
|
||||
|
||||
ZFS_DATASET=
|
||||
ZFS_POOL=
|
||||
|
||||
if [ "${root}" = "zfs:AUTO" ] ; then
|
||||
if ! ZFS_DATASET="$(find_bootfs)" ; then
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -53,7 +42,7 @@ if [ "${root}" = "zfs:AUTO" ] ; then
|
|||
info "ZFS: Using ${ZFS_DATASET} as root."
|
||||
fi
|
||||
|
||||
ZFS_DATASET="${ZFS_DATASET:-${root#zfs:}}"
|
||||
ZFS_DATASET="${ZFS_DATASET:-${root}}"
|
||||
ZFS_POOL="${ZFS_DATASET%%/*}"
|
||||
|
||||
if import_pool "${ZFS_POOL}" ; then
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#!/bin/sh
|
||||
# shellcheck disable=SC2034,SC2154
|
||||
|
||||
. /lib/dracut-lib.sh
|
||||
# shellcheck source=zfs-lib.sh.in
|
||||
. /lib/dracut-zfs-lib.sh
|
||||
|
||||
# Let the command line override our host id.
|
||||
spl_hostid=$(getarg spl_hostid=)
|
||||
|
@ -15,46 +16,20 @@ else
|
|||
warn "ZFS: Pools may not import correctly."
|
||||
fi
|
||||
|
||||
wait_for_zfs=0
|
||||
case "${root}" in
|
||||
""|zfs|zfs:)
|
||||
# We'll take root unset, root=zfs, or root=zfs:
|
||||
# No root set, so we want to read the bootfs attribute. We
|
||||
# can't do that until udev settles so we'll set dummy values
|
||||
# and hope for the best later on.
|
||||
root="zfs:AUTO"
|
||||
rootok=1
|
||||
wait_for_zfs=1
|
||||
if decode_root_args; then
|
||||
if [ "$root" = "zfs:AUTO" ]; then
|
||||
info "ZFS: Boot dataset autodetected from bootfs=."
|
||||
else
|
||||
info "ZFS: Boot dataset is ${root}."
|
||||
fi
|
||||
|
||||
info "ZFS: Enabling autodetection of bootfs after udev settles."
|
||||
;;
|
||||
|
||||
ZFS=*|zfs:*)
|
||||
# root is explicit ZFS root. Parse it now. We can handle
|
||||
# a root=... param in any of the following formats:
|
||||
# root=ZFS=rpool/ROOT
|
||||
# root=zfs:rpool/ROOT
|
||||
# root=ZFS=pool+with+space/ROOT+WITH+SPACE (translates to root=ZFS=pool with space/ROOT WITH SPACE)
|
||||
|
||||
# Strip down to just the pool/fs
|
||||
root="${root#zfs:}"
|
||||
root="zfs:${root#ZFS=}"
|
||||
# switch + with spaces because kernel cmdline does not allow us to quote parameters
|
||||
root=$(echo "$root" | tr '+' ' ')
|
||||
rootok=1
|
||||
wait_for_zfs=1
|
||||
|
||||
info "ZFS: Set ${root} as bootfs."
|
||||
;;
|
||||
|
||||
*)
|
||||
info "ZFS: no ZFS-on-root"
|
||||
esac
|
||||
|
||||
# Make sure Dracut is happy that we have a root and will wait for ZFS
|
||||
# modules to settle before mounting.
|
||||
if [ "${wait_for_zfs}" -eq 1 ]; then
|
||||
ln -s /dev/null /dev/root 2>/dev/null
|
||||
initqueuedir="${hookdir}/initqueue/finished"
|
||||
echo '[ -e /dev/zfs ]' > "${initqueuedir}/zfs.sh"
|
||||
rootok=1
|
||||
# Make sure Dracut is happy that we have a root and will wait for ZFS
|
||||
# modules to settle before mounting.
|
||||
if [ -n "${wait_for_zfs}" ]; then
|
||||
ln -s null /dev/root
|
||||
echo '[ -e /dev/zfs ]' > "${hookdir}/initqueue/finished/zfs.sh"
|
||||
fi
|
||||
else
|
||||
info "ZFS: no ZFS-on-root."
|
||||
fi
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/sh
|
||||
# shellcheck disable=SC2016,SC1004
|
||||
# shellcheck disable=SC2016,SC1004,SC2154
|
||||
|
||||
grep -wq debug /proc/cmdline && debug=1
|
||||
[ -n "$debug" ] && echo "zfs-generator: starting" >> /dev/kmsg
|
||||
|
@ -10,37 +10,17 @@ GENERATOR_DIR="$1"
|
|||
exit 1
|
||||
}
|
||||
|
||||
[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
|
||||
[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
|
||||
command -v getarg >/dev/null 2>&1 || {
|
||||
[ -n "$debug" ] && echo "zfs-generator: loading Dracut library from $dracutlib" >> /dev/kmsg
|
||||
. "$dracutlib"
|
||||
}
|
||||
|
||||
# shellcheck source=zfs-lib.sh.in
|
||||
. /lib/dracut-zfs-lib.sh
|
||||
decode_root_args || exit 0
|
||||
|
||||
[ -z "$root" ] && root=$(getarg root=)
|
||||
[ -z "$rootfstype" ] && rootfstype=$(getarg rootfstype=)
|
||||
[ -z "$rootflags" ] && rootflags=$(getarg rootflags=)
|
||||
|
||||
# If root is not ZFS= or zfs: or rootfstype is not zfs
|
||||
# then we are not supposed to handle it.
|
||||
[ "${root##zfs:}" = "${root}" ] &&
|
||||
[ "${root##ZFS=}" = "${root}" ] &&
|
||||
[ "$rootfstype" != "zfs" ] &&
|
||||
exit 0
|
||||
|
||||
[ -z "${rootflags}" ] && rootflags=$(getarg rootflags=)
|
||||
case ",${rootflags}," in
|
||||
*,zfsutil,*) ;;
|
||||
,,) rootflags=zfsutil ;;
|
||||
*) rootflags="zfsutil,${rootflags}" ;;
|
||||
esac
|
||||
|
||||
if [ "${root}" != "zfs:AUTO" ]; then
|
||||
root="${root##zfs:}"
|
||||
root="${root##ZFS=}"
|
||||
fi
|
||||
|
||||
[ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg
|
||||
|
||||
|
||||
|
@ -89,7 +69,7 @@ else
|
|||
_zfs_generator_cb() {
|
||||
dset="${1}"
|
||||
mpnt="${2}"
|
||||
unit="sysroot$(echo "$mpnt" | tr '/' '-').mount"
|
||||
unit="$(systemd-escape --suffix=mount -p "/sysroot${mpnt}")"
|
||||
|
||||
{
|
||||
echo "[Unit]"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
command -v getarg >/dev/null || . /lib/dracut-lib.sh
|
||||
command -v getarg >/dev/null || . /lib/dracut-lib.sh || . /usr/lib/dracut/modules.d/99base/dracut-lib.sh
|
||||
command -v getargbool >/dev/null || {
|
||||
# Compatibility with older Dracut versions.
|
||||
# With apologies to the Dracut developers.
|
||||
|
@ -161,7 +161,9 @@ ask_for_password() {
|
|||
shift
|
||||
done
|
||||
|
||||
{ flock -s 9;
|
||||
{
|
||||
flock -s 9
|
||||
|
||||
# Prompt for password with plymouth, if installed and running.
|
||||
if plymouth --ping 2>/dev/null; then
|
||||
plymouth ask-for-password \
|
||||
|
@ -191,3 +193,58 @@ ask_for_password() {
|
|||
[ "$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
|
||||
#
|
||||
# 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
|
||||
}
|
||||
|
|
|
@ -4,32 +4,20 @@
|
|||
# only run this on systemd systems, we handle the decrypt in mount-zfs.sh in the mount hook otherwise
|
||||
[ -e /bin/systemctl ] || [ -e /usr/bin/systemctl ] || return 0
|
||||
|
||||
# This script only gets executed on systemd systems, see mount-zfs.sh for non-systemd systems
|
||||
# shellcheck source=zfs-lib.sh.in
|
||||
. /lib/dracut-zfs-lib.sh
|
||||
|
||||
# import the libs now that we know the pool imported
|
||||
[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
|
||||
[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
|
||||
# shellcheck source=./lib-zfs.sh.in
|
||||
. "$dracutlib"
|
||||
|
||||
# load the kernel command line vars
|
||||
[ -z "$root" ] && root="$(getarg root=)"
|
||||
# If root is not ZFS= or zfs: or rootfstype is not zfs then we are not supposed to handle it.
|
||||
[ "${root##zfs:}" = "${root}" ] && [ "${root##ZFS=}" = "${root}" ] && [ "$rootfstype" != "zfs" ] && exit 0
|
||||
decode_root_args || return 0
|
||||
|
||||
# There is a race between the zpool import and the pre-mount hooks, so we wait for a pool to be imported
|
||||
while [ "$(zpool list -H)" = "" ]; do
|
||||
systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && exit 1
|
||||
while ! systemctl is-active --quiet zfs-import.target; do
|
||||
systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && return 1
|
||||
sleep 0.1s
|
||||
done
|
||||
|
||||
# run this after import as zfs-import-cache/scan service is confirmed good
|
||||
# we do not overwrite the ${root} variable, but create a new one, BOOTFS, to hold the dataset
|
||||
if [ "${root}" = "zfs:AUTO" ] ; then
|
||||
BOOTFS="$(zpool list -H -o bootfs | awk '$1 != "-" {print; exit}')"
|
||||
else
|
||||
BOOTFS="${root##zfs:}"
|
||||
BOOTFS="${BOOTFS##ZFS=}"
|
||||
BOOTFS="$root"
|
||||
if [ "$BOOTFS" = "zfs:AUTO" ]; then
|
||||
BOOTFS="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"
|
||||
fi
|
||||
|
||||
# if pool encryption is active and the zfs command understands '-o encryption'
|
||||
|
|
|
@ -16,18 +16,18 @@ Encrypted datasets have keys loaded automatically or prompted for.
|
|||
If the root dataset contains children with `mountpoint=`s of `/etc`, `/bin`, `/lib*`, or `/usr`, they're mounted too.
|
||||
|
||||
## cmdline
|
||||
1. `root=` | Root dataset is… | Pools imported |
|
||||
-------------------|----------------------------------------------------------|----------------|
|
||||
*(empty)* | the first `bootfs=` after `zpool import -aN` | all |
|
||||
`zfs:AUTO` | *(as above, but overriding other autoselection methods)* | all |
|
||||
`ZFS=pool/dataset` | `pool/dataset` | `pool` |
|
||||
`zfs:pool/dataset` | *(as above)* | `pool` |
|
||||
1. `root=` | Root dataset is… |
|
||||
---------------------------|----------------------------------------------------------|
|
||||
*(empty)* | the first `bootfs=` after `zpool import -aN` |
|
||||
`zfs:AUTO`, `zfs:`, `zfs` | *(as above, but overriding other autoselection methods)* |
|
||||
`ZFS=pool/dataset` | `pool/dataset` |
|
||||
`zfs:pool/dataset` | *(as above)* |
|
||||
|
||||
All `+`es are replaced with spaces (i.e. to boot from `root pool/data set`, pass `root=zfs:root+pool/data+set`).
|
||||
|
||||
The dataset can be at any depth, including being the pool's root dataset (i.e. `root=zfs:pool`).
|
||||
|
||||
`rootfstype=zfs` is mostly equivalent to `root=zfs:AUTO`.
|
||||
`rootfstype=zfs` is equivalent to `root=zfs:AUTO`, `rootfstype=zfs root=pool/dataset` is equivalent to `root=zfs:pool/dataset`.
|
||||
|
||||
2. `spl_hostid`: passed to `zgenhostid -f`, useful to override the `/etc/hostid` file baked into the initrd.
|
||||
|
||||
|
|
Loading…
Reference in New Issue