From d402c18dd60124525b253b27c5018f54a030928d Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Sun, 24 Apr 2016 11:35:44 +0000 Subject: [PATCH] A collection of dracut fixes - In older systems without sysroot.mount, import before dracut-mount, and re-enable old dracut mount hook - rootflags MUST be present even if the administrator neglected to specify it explicitly - Check that mount.zfs exists in sbindir - Remove awk and head as (now unused) requirements, add grep, and install the right mount.zfs - Eliminate one use of grep in Dracut - Use a more accurate grepping statement to identify zfsutil in rootflags - Ensure that pooldev is nonempty - Properly handle /dev/sd* devices and more - Use new -P to get list of zpool devices - Bail out of the generator when zfs:AUTO is on the root command line - Ignore errors from systemctl trying to load sysroot.mount, we only care about the output - Determine which one is the correct initqueuedir at run time. - Add a compatibility getargbool for our detection / setup script. - Update dracut .gitignore files Signed-off-by: Signed-off-by: Brian Behlendorf Closes #4558 Closes #4562 --- .../dracut/02zfsexpandknowledge/.gitignore | 1 + .../02zfsexpandknowledge/module-setup.sh.in | 19 +++++++++++-------- contrib/dracut/90zfs/.gitignore | 1 + contrib/dracut/90zfs/module-setup.sh.in | 17 +++++++++-------- contrib/dracut/90zfs/mount-zfs.sh.in | 10 ++++++++++ contrib/dracut/90zfs/parse-zfs.sh.in | 6 +++++- contrib/dracut/90zfs/zfs-generator.sh.in | 10 +++++++++- contrib/dracut/90zfs/zfs-lib.sh.in | 18 ++++++++++++++++++ .../system/zfs-import-cache.service.in | 1 + etc/systemd/system/zfs-import-scan.service.in | 1 + 10 files changed, 66 insertions(+), 18 deletions(-) create mode 100644 contrib/dracut/02zfsexpandknowledge/.gitignore mode change 100644 => 100755 contrib/dracut/90zfs/zfs-generator.sh.in diff --git a/contrib/dracut/02zfsexpandknowledge/.gitignore b/contrib/dracut/02zfsexpandknowledge/.gitignore new file mode 100644 index 0000000000..7fb6b964f0 --- /dev/null +++ b/contrib/dracut/02zfsexpandknowledge/.gitignore @@ -0,0 +1 @@ +module-setup.sh diff --git a/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in b/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in index 830ee42f64..e694ae0d02 100755 --- a/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in +++ b/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in @@ -15,21 +15,24 @@ get_pool_devices() { local poolconfigoutput local pooldev local prefix + local resolved poolconfigtemp=`mktemp` - @sbindir@/zpool list -v -H "$1" > "$poolconfigtemp" 2>&1 + @sbindir@/zpool list -v -H -P "$1" > "$poolconfigtemp" 2>&1 if [ "$?" != "0" ] ; then poolconfigoutput=$(cat "$poolconfigtemp") dinfo "zfsexpandknowledge: pool $1 cannot be listed: $poolconfigoutput" else while read pooldev ; do - for prefix in /dev/disk/* /dev/mapper ; do - if [ -e "$prefix"/"$pooldev" ] ; then - dinfo "zfsexpandknowledge: pool $1 has device $prefix/$pooldev" - echo `readlink -f "$prefix"/"$pooldev"` - break + if [ -n "$pooldev" -a -e "$pooldev" ] ; then + if [ -h "$pooldev" ] ; then + resolved=`readlink -f "$pooldev"` + else + resolved="$pooldev" + fi + dinfo "zfsexpandknowledge: pool $1 has device $pooldev (which resolves to $resolved)" + echo "$resolved" fi - done - done < <(cat "$poolconfigtemp" | awk -F '\t' 'NR>1 { print $2 }') + done < <(cat "$poolconfigtemp" | awk -F '\t' '/\t\/dev/ { print $2 }') fi rm -f "$poolconfigtemp" } diff --git a/contrib/dracut/90zfs/.gitignore b/contrib/dracut/90zfs/.gitignore index 9502be9851..098a7510ea 100644 --- a/contrib/dracut/90zfs/.gitignore +++ b/contrib/dracut/90zfs/.gitignore @@ -2,4 +2,5 @@ export-zfs.sh module-setup.sh mount-zfs.sh parse-zfs.sh +zfs-generator.sh zfs-lib.sh diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in index 301375a5b3..70eac87903 100755 --- a/contrib/dracut/90zfs/module-setup.sh.in +++ b/contrib/dracut/90zfs/module-setup.sh.in @@ -5,8 +5,11 @@ check() { [ "${1}" = "-d" ] && return 0 # Verify the zfs tool chain - which zpool >/dev/null 2>&1 || return 1 - which zfs >/dev/null 2>&1 || return 1 + for tool in "@sbindir@/zpool" "@sbindir@/zfs" "@sbindir@/mount.zfs" ; do + test -x "$tool" || return 1 + done + # Verify grep exists + which grep >/dev/null 2>&1 || return 1 return 0 } @@ -31,20 +34,18 @@ install() { inst_rules @udevruledir@/90-zfs.rules inst_rules @udevruledir@/69-vdev.rules inst_rules @udevruledir@/60-zvol.rules + dracut_install hostid + dracut_install grep dracut_install @sbindir@/zfs dracut_install @sbindir@/zpool + dracut_install @sbindir@/mount.zfs dracut_install @udevdir@/vdev_id dracut_install @udevdir@/zvol_id - dracut_install mount.zfs - dracut_install hostid - dracut_install awk - dracut_install head inst_hook cmdline 95 "${moddir}/parse-zfs.sh" if [ -n "$systemdutildir" ] ; then inst_script "${moddir}/zfs-generator.sh" "$systemdutildir"/system-generators/dracut-zfs-generator - else - inst_hook mount 98 "${moddir}/mount-zfs.sh" fi + inst_hook mount 98 "${moddir}/mount-zfs.sh" inst_hook shutdown 30 "${moddir}/export-zfs.sh" inst_simple "${moddir}/zfs-lib.sh" "/lib/dracut-zfs-lib.sh" diff --git a/contrib/dracut/90zfs/mount-zfs.sh.in b/contrib/dracut/90zfs/mount-zfs.sh.in index 2abc8766b5..43862fa8f6 100755 --- a/contrib/dracut/90zfs/mount-zfs.sh.in +++ b/contrib/dracut/90zfs/mount-zfs.sh.in @@ -10,6 +10,16 @@ case "${root}" in *) return ;; esac +# If sysroot.mount exists, the initial RAM disk configured +# it to mount ZFS on root. In that case, we bail early. +loadstate="$(systemctl --system --show -p LoadState sysroot.mount || true)" +if [ "${loadstate}" = "LoadState=not-found" -o "${loadstate}" = "" ] ; then + info "ZFS: sysroot.mount absent, mounting root with mount-zfs.sh" +else + info "ZFS: sysroot.mount present, delegating root mount to it" + return +fi + # Delay until all required block devices are present. udevadm settle diff --git a/contrib/dracut/90zfs/parse-zfs.sh.in b/contrib/dracut/90zfs/parse-zfs.sh.in index c305c78217..74a426ebb1 100755 --- a/contrib/dracut/90zfs/parse-zfs.sh.in +++ b/contrib/dracut/90zfs/parse-zfs.sh.in @@ -55,5 +55,9 @@ esac # modules to settle before mounting. if [ ${wait_for_zfs} -eq 1 ]; then ln -s /dev/null /dev/root 2>/dev/null - echo '[ -e /dev/zfs ]' > "${hookdir}/initqueue/finished/zfs.sh" + initqueuedir="${hookdir}/initqueue/finished" + test -d initqueuedir || { + initqueuedir="${hookdir}/initqueue-finished" + } + echo '[ -e /dev/zfs ]' > "${initqueuedir}/zfs.sh" fi diff --git a/contrib/dracut/90zfs/zfs-generator.sh.in b/contrib/dracut/90zfs/zfs-generator.sh.in old mode 100644 new mode 100755 index 0e0664d0ac..aa12fb856d --- a/contrib/dracut/90zfs/zfs-generator.sh.in +++ b/contrib/dracut/90zfs/zfs-generator.sh.in @@ -13,10 +13,18 @@ type getarg >/dev/null 2>&1 || . "$dracutlib" [ -z "$rootflags" ] && rootflags=$(getarg rootflags=) [ "${root##zfs:}" = "${root}" -a "${root##ZFS=}" = "${root}" -a "$rootfstype" != "zfs" ] && exit 0 +# If root is set to zfs:AUTO, then we know sysroot.mount will not be generated +# so we have no need to enhance it. +# See https://github.com/zfsonlinux/zfs/pull/4558#discussion_r61118952 for details. +if [ "${root}" = "zfs:AUTO" ] ; then + exit 0 +fi rootfstype=zfs -if echo "${rootflags}" | grep -q zfsutil ; then +if echo "${rootflags}" | grep -Eq '^zfsutil$|^zfsutil,|,zfsutil$|,zfsutil,' ; then true +elif test -n "${rootflags}" ; then + rootflags="zfsutil,${rootflags}" else rootflags=zfsutil fi diff --git a/contrib/dracut/90zfs/zfs-lib.sh.in b/contrib/dracut/90zfs/zfs-lib.sh.in index 1c223befd0..c822ddb9d7 100755 --- a/contrib/dracut/90zfs/zfs-lib.sh.in +++ b/contrib/dracut/90zfs/zfs-lib.sh.in @@ -1,6 +1,24 @@ #!/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() { + local _b + unset _b + local _default + _default="$1"; shift + _b=$(getarg "$@") + [ $? -ne 0 -a -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=" diff --git a/etc/systemd/system/zfs-import-cache.service.in b/etc/systemd/system/zfs-import-cache.service.in index b1deb6ed96..a567b3095b 100644 --- a/etc/systemd/system/zfs-import-cache.service.in +++ b/etc/systemd/system/zfs-import-cache.service.in @@ -4,6 +4,7 @@ DefaultDependencies=no Requires=systemd-udev-settle.service After=systemd-udev-settle.service After=cryptsetup.target +Before=dracut-mount.service ConditionPathExists=@sysconfdir@/zfs/zpool.cache [Service] diff --git a/etc/systemd/system/zfs-import-scan.service.in b/etc/systemd/system/zfs-import-scan.service.in index 517e12e3a2..cb3c2a7bdb 100644 --- a/etc/systemd/system/zfs-import-scan.service.in +++ b/etc/systemd/system/zfs-import-scan.service.in @@ -4,6 +4,7 @@ DefaultDependencies=no Requires=systemd-udev-settle.service After=systemd-udev-settle.service After=cryptsetup.target +Before=dracut-mount.service ConditionPathExists=!@sysconfdir@/zfs/zpool.cache [Service]