aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/dracut/90zfs
diff options
context:
space:
mode:
authorRudd-O <[email protected]>2016-10-06 17:26:47 +0000
committerBrian Behlendorf <[email protected]>2016-10-06 10:26:47 -0700
commitb0f578a8073da49dd0af879944a1b8e8dfd6db56 (patch)
tree8ff70c9bbd1982cb99fdb55a30957f88a395b3ca /contrib/dracut/90zfs
parent64c688d7161daac0a799b11b40cb791f6fd264db (diff)
Use a different technique to detect whether to mount-zfs
The behavior of the Dracut module was very wrong before. The correct behavior: initramfs should not run `zfs-mount` to completion if the two generator files exist. If, however, one of them is missing, it indicates one of three cases: * The kernel command line did not specify a root ZFS file system, and another Dracut module is already handling root mount (via systemd). `mount-zfs` can run, but it will do nothing. * There is no systemd to run `sysroot.mount` to begin with. `mount-zfs` must run. * The root parameter is zfs:AUTO, which cannot be run in sysroot.mount. `mount-zfs` must run. In any of these three cases, it is safe to run `zfs-mount` to completion. `zfs-mount` must also delete itself if it determines it should not run, or else Dracut will do the insane thing of running it over and over again. Literally, the definition of insanity, doing the same thing that did not work before, expecting different results. Doing that may have had a great result before, when we had a race between devices appearing and pools being mounted, and `mount-zfs` was tasked with the full responsibility of importing the needed pool, but nowadays it is wrong behavior and should be suppressed. I deduced that self-deletion was the correct thing to do by looking at other Dracut code, because (as we all are very fully aware of) Dracut is entirely, ahem, "implementation-defined". Tested-by: @wphilips Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Manuel Amador (Rudd-O) <[email protected]> Closes #5157 Closes #5204
Diffstat (limited to 'contrib/dracut/90zfs')
-rwxr-xr-xcontrib/dracut/90zfs/mount-zfs.sh.in37
-rwxr-xr-xcontrib/dracut/90zfs/zfs-generator.sh.in34
2 files changed, 52 insertions, 19 deletions
diff --git a/contrib/dracut/90zfs/mount-zfs.sh.in b/contrib/dracut/90zfs/mount-zfs.sh.in
index 51e107bb3..3b6be314c 100755
--- a/contrib/dracut/90zfs/mount-zfs.sh.in
+++ b/contrib/dracut/90zfs/mount-zfs.sh.in
@@ -10,17 +10,29 @@ case "${root}" in
*) return ;;
esac
-if command -v systemctl >/dev/null; then
- # 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
+GENERATOR_FILE=/run/systemd/generator/sysroot.mount
+GENERATOR_EXTENSION=/run/systemd/generator/sysroot.mount.d/zfs-enhancement.conf
+
+if [ -e "$GENERATOR_FILE" -a -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.
+ need_shutdown
+ # 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.
udevadm settle
@@ -45,6 +57,10 @@ ZFS_DATASET="${ZFS_DATASET:-${root#zfs:}}"
ZFS_POOL="${ZFS_DATASET%%/*}"
if import_pool "${ZFS_POOL}" ; then
+ # Let us tell the initrd to run on shutdown.
+ # We have a shutdown hook to run
+ # because we imported the pool.
+ need_shutdown
info "ZFS: Mounting dataset ${ZFS_DATASET}..."
if mount_dataset "${ZFS_DATASET}" ; then
ROOTFS_MOUNTED=yes
@@ -53,4 +69,3 @@ if import_pool "${ZFS_POOL}" ; then
fi
rootok=0
-need_shutdown
diff --git a/contrib/dracut/90zfs/zfs-generator.sh.in b/contrib/dracut/90zfs/zfs-generator.sh.in
index aa12fb856..c6384f583 100755
--- a/contrib/dracut/90zfs/zfs-generator.sh.in
+++ b/contrib/dracut/90zfs/zfs-generator.sh.in
@@ -1,21 +1,32 @@
#!/bin/bash
+echo "zfs-generator: starting" >> /dev/kmsg
+
GENERATOR_DIR="$1"
-[ -z "$GENERATOR_DIR" ] && exit 1
+[ -n "$GENERATOR_DIR" ] || {
+ echo "zfs-generator: no generator directory specified, exiting" >> /dev/kmsg
+ 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
-type getarg >/dev/null 2>&1 || . "$dracutlib"
+type getarg >/dev/null 2>&1 || {
+ echo "zfs-generator: loading Dracut library from $dracutlib" >> /dev/kmsg
+ . "$dracutlib"
+}
[ -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}" -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 is set to zfs:AUTO, then we are also not
+# supposed to handle it, and it should be handled
+# by the traditional Dracut mount hook.
+# See https://github.com/zfsonlinux/zfs/pull/4558#discussion_r61118952
if [ "${root}" = "zfs:AUTO" ] ; then
exit 0
fi
@@ -32,16 +43,23 @@ fi
root="${root##zfs:}"
root="${root##ZFS=}"
+echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR"/sysroot.mount.d/zfs-enhancement.conf >> /dev/kmsg
+
[ -d "$GENERATOR_DIR" ] || mkdir "$GENERATOR_DIR"
-[ -d "$GENERATOR_DIR/sysroot.mount.d" ] || mkdir "$GENERATOR_DIR/sysroot.mount.d"
+[ -d "$GENERATOR_DIR"/sysroot.mount.d ] || mkdir "$GENERATOR_DIR"/sysroot.mount.d
{
echo "[Unit]"
+ echo "Before=initrd-root-fs.target"
echo "After=zfs-import-scan.service"
echo "After=zfs-import-cache.service"
- echo ""
echo "[Mount]"
echo "What=${root}"
echo "Type=${rootfstype}"
echo "Options=${rootflags}"
-} > "$GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf"
+} > "$GENERATOR_DIR"/sysroot.mount.d/zfs-enhancement.conf
+
+[ -d "$GENERATOR_DIR"/initrd-root-fs.target.requires ] || mkdir -p "$GENERATOR_DIR"/initrd-root-fs.target.requires
+ln -s ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount
+
+echo "zfs-generator: finished" >> /dev/kmsg