+From a5a370227eb0a3daf8992a38920d54eb3b7b3c25 Mon Sep 17 00:00:00 2001
+From: Matthew Thode <mthode@mthode.org>
+Date: Wed, 30 Mar 2016 18:59:15 -0500
+Subject: [PATCH 001/530] fix booting via dracut generated initramfs
+
+Dracut and Systemd updated how they integrate with each other, because
+of this our current integrations stopped working (around the time
+4.1.13 came out). This patch addresses that issue and gets us booting
+again.
+
+Thanks to @Rudd-O for doing the work to get dracut working again and
+letting me submit this on his behalf.
+
+Signed-off-by: Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
+Signed-off-by: Matthew Thode <mthode@mthode.org>
+Closes #3605
+Closes #4478
+---
+ configure.ac | 1 +
+ contrib/dracut/02zfsexpandknowledge/Makefile.am | 22 ++++
+ .../dracut/02zfsexpandknowledge/module-setup.sh.in | 132 +++++++++++++++++++++
+ contrib/dracut/90zfs/Makefile.am | 3 +
+ contrib/dracut/90zfs/module-setup.sh.in | 19 ++-
+ contrib/dracut/90zfs/zfs-generator.sh.in | 39 ++++++
+ contrib/dracut/Makefile.am | 2 +-
+ 7 files changed, 216 insertions(+), 2 deletions(-)
+ create mode 100644 contrib/dracut/02zfsexpandknowledge/Makefile.am
+ create mode 100755 contrib/dracut/02zfsexpandknowledge/module-setup.sh.in
+ create mode 100644 contrib/dracut/90zfs/zfs-generator.sh.in
+
+diff --git a/configure.ac b/configure.ac
+index 41cd007..5037ccb 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -114,6 +114,7 @@ AC_CONFIG_FILES([
+ contrib/Makefile
+ contrib/bash_completion.d/Makefile
+ contrib/dracut/Makefile
++ contrib/dracut/02zfsexpandknowledge/Makefile
+ contrib/dracut/90zfs/Makefile
+ contrib/initramfs/Makefile
+ module/Makefile
+diff --git a/contrib/dracut/02zfsexpandknowledge/Makefile.am b/contrib/dracut/02zfsexpandknowledge/Makefile.am
+new file mode 100644
+index 0000000..0a2170b
+--- /dev/null
++++ b/contrib/dracut/02zfsexpandknowledge/Makefile.am
+@@ -0,0 +1,22 @@
++pkgdracutdir = $(dracutdir)/modules.d/02zfsexpandknowledge
++pkgdracut_SCRIPTS = \
++ module-setup.sh
++
++EXTRA_DIST = \
++ $(top_srcdir)/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in
++
++$(pkgdracut_SCRIPTS):
++ -$(SED) -e 's,@bindir\@,$(bindir),g' \
++ -e 's,@sbindir\@,$(sbindir),g' \
++ -e 's,@datadir\@,$(datadir),g' \
++ -e 's,@dracutdir\@,$(dracutdir),g' \
++ -e 's,@udevdir\@,$(udevdir),g' \
++ -e 's,@udevruledir\@,$(udevruledir),g' \
++ -e 's,@sysconfdir\@,$(sysconfdir),g' \
++ "$(top_srcdir)/contrib/dracut/02zfsexpandknowledge/$@.in" >'$@'
++
++clean-local::
++ -$(RM) $(pkgdracut_SCRIPTS)
++
++distclean-local::
++ -$(RM) $(pkgdracut_SCRIPTS)
+diff --git a/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in b/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in
+new file mode 100755
+index 0000000..830ee42
+--- /dev/null
++++ b/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in
+@@ -0,0 +1,132 @@
++#!/bin/sh
++
++get_devtype() {
++ local typ
++ typ=$(udevadm info --query=property --name="$1" | grep "^ID_FS_TYPE=" | sed 's|^ID_FS_TYPE=||')
++ if [ "$typ" = "" ] ; then
++ typ=$(blkid -c /dev/null "$1" -o value -s TYPE)
++ fi
++ echo "$typ"
++}
++
++get_pool_devices() {
++ # also present in 99zfssystemd
++ local poolconfigtemp
++ local poolconfigoutput
++ local pooldev
++ local prefix
++ poolconfigtemp=`mktemp`
++ @sbindir@/zpool list -v -H "$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
++ fi
++ done
++ done < <(cat "$poolconfigtemp" | awk -F '\t' 'NR>1 { print $2 }')
++ fi
++ rm -f "$poolconfigtemp"
++}
++
++find_zfs_block_devices() {
++ local dev
++ local blockdev
++ local mp
++ local fstype
++ local pool
++ local key
++ local n
++ local poolconfigoutput
++ numfields=`head -1 /proc/self/mountinfo | awk '{print NF}'`
++ if [ "$numfields" == "10" ] ; then
++ fields="n n n n mp n n fstype dev n"
++ else
++ fields="n n n n mp n n n fstype dev n"
++ fi
++ while read $fields ; do
++ if [ "$fstype" != "zfs" ]; then continue ; fi
++ if [ "$mp" == "$1" ]; then
++ pool=$(echo "$dev" | cut -d / -f 1)
++ get_pool_devices "$pool"
++ fi
++ done < /proc/self/mountinfo
++}
++
++array_contains () {
++ local e
++ for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
++ return 1
++}
++
++check() {
++ local mp
++ local dev
++ local blockdevs
++ local fstype
++ local majmin
++ local _slavedev
++ local _slavedevname
++ local _slavedevtype
++ local _slavemajmin
++ local _dev
++
++if [[ $hostonly ]]; then
++
++ for mp in \
++ "/" \
++ "/etc" \
++ "/bin" \
++ "/sbin" \
++ "/lib" \
++ "/lib64" \
++ "/usr" \
++ "/usr/bin" \
++ "/usr/sbin" \
++ "/usr/lib" \
++ "/usr/lib64" \
++ "/boot";
++ do
++ mp=$(readlink -f "$mp")
++ mountpoint "$mp" >/dev/null 2>&1 || continue
++ blockdevs=$(find_zfs_block_devices "$mp")
++ if [ -z "$blockdevs" ] ; then continue ; fi
++ dinfo "zfsexpandknowledge: block devices backing ZFS dataset $mp: $blockdevs"
++ for dev in $blockdevs
++ do
++ array_contains "$dev" "${host_devs[@]}" || host_devs+=("$dev")
++ fstype=$(get_devtype "$dev")
++ host_fs_types["$dev"]="$fstype"
++ majmin=$(get_maj_min "$dev")
++ if [[ -d /sys/dev/block/$majmin/slaves ]] ; then
++ for _slavedev in /sys/dev/block/$majmin/slaves/*; do
++ [[ -f $_slavedev/dev ]] || continue
++ _slavedev=/dev/$(basename "$_slavedev")
++ _slavedevname=$(udevadm info --query=property --name="$_slavedev" | grep "^DEVNAME=" | sed 's|^DEVNAME=||')
++ _slavedevtype=$(get_devtype "$_slavedevname")
++ _slavemajmin=$(get_maj_min "$_slavedevname")
++ dinfo "zfsexpandknowledge: slave block device backing ZFS dataset $mp: $_slavedevname"
++ array_contains "$_slavedevname" "${host_devs[@]}" || host_devs+=("$_slavedevname")
++ host_fs_types["$_slavedevname"]="$_slavedevtype"
++ done
++ fi
++ done
++ done
++ for a in "${host_devs[@]}"
++ do
++ dinfo "zfsexpandknowledge: host device $a"
++ done
++ for a in "${!host_fs_types[@]}"
++ do
++ dinfo "zfsexpandknowledge: device $a of type ${host_fs_types[$a]}"
++ done
++
++fi
++
++return 1
++}
+diff --git a/contrib/dracut/90zfs/Makefile.am b/contrib/dracut/90zfs/Makefile.am
+index b778a27..f81d6c3 100644
+--- a/contrib/dracut/90zfs/Makefile.am
++++ b/contrib/dracut/90zfs/Makefile.am
+@@ -4,6 +4,7 @@ pkgdracut_SCRIPTS = \
+ module-setup.sh \
+ mount-zfs.sh \
+ parse-zfs.sh \
++ zfs-generator.sh \
+ zfs-lib.sh
+
+ EXTRA_DIST = \
+@@ -11,6 +12,7 @@ EXTRA_DIST = \
+ $(top_srcdir)/contrib/dracut/90zfs/module-setup.sh.in \
+ $(top_srcdir)/contrib/dracut/90zfs/mount-zfs.sh.in \
+ $(top_srcdir)/contrib/dracut/90zfs/parse-zfs.sh.in \
++ $(top_srcdir)/contrib/dracut/90zfs/zfs-generator.sh.in \
+ $(top_srcdir)/contrib/dracut/90zfs/zfs-lib.sh.in
+
+ $(pkgdracut_SCRIPTS):
+@@ -19,6 +21,7 @@ $(pkgdracut_SCRIPTS):
+ -e 's,@udevdir\@,$(udevdir),g' \
+ -e 's,@udevruledir\@,$(udevruledir),g' \
+ -e 's,@sysconfdir\@,$(sysconfdir),g' \
++ -e 's,@systemdunitdir\@,$(systemdunitdir),g' \
+ "$(top_srcdir)/contrib/dracut/90zfs/$@.in" >'$@'
+
+ distclean-local::
+diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in
+index 9eb9f57..301375a 100755
+--- a/contrib/dracut/90zfs/module-setup.sh.in
++++ b/contrib/dracut/90zfs/module-setup.sh.in
+@@ -40,16 +40,22 @@ install() {
+ dracut_install awk
+ dracut_install head
+ inst_hook cmdline 95 "${moddir}/parse-zfs.sh"
+- inst_hook mount 98 "${moddir}/mount-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 shutdown 30 "${moddir}/export-zfs.sh"
+
+ inst_simple "${moddir}/zfs-lib.sh" "/lib/dracut-zfs-lib.sh"
+ if [ -e @sysconfdir@/zfs/zpool.cache ]; then
+ inst @sysconfdir@/zfs/zpool.cache
++ type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/zfs/zpool.cache
+ fi
+
+ if [ -e @sysconfdir@/zfs/vdev_id.conf ]; then
+ inst @sysconfdir@/zfs/vdev_id.conf
++ type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/zfs/vdev_id.conf
+ fi
+
+ # Synchronize initramfs and system hostid
+@@ -58,4 +64,15 @@ install() {
+ CC=`hostid | cut -b 5,6`
+ DD=`hostid | cut -b 7,8`
+ printf "\x${DD}\x${CC}\x${BB}\x${AA}" > "${initdir}/etc/hostid"
++
++ if dracut_module_included "systemd"; then
++ mkdir -p "${initdir}/$systemdsystemunitdir/initrd.target.wants"
++ for _item in scan cache ; do
++ dracut_install @systemdunitdir@/zfs-import-$_item.service
++ if ! [ -L "${initdir}/$systemdsystemunitdir/initrd.target.wants"/zfs-import-$_item.service ]; then
++ ln -s ../zfs-import-$_item.service "${initdir}/$systemdsystemunitdir/initrd.target.wants"/zfs-import-$_item.service
++ type mark_hostonly >/dev/null 2>&1 && mark_hostonly @systemdunitdir@/zfs-import-$_item.service
++ fi
++ done
++ fi
+ }
+diff --git a/contrib/dracut/90zfs/zfs-generator.sh.in b/contrib/dracut/90zfs/zfs-generator.sh.in
+new file mode 100644
+index 0000000..0e0664d
+--- /dev/null
++++ b/contrib/dracut/90zfs/zfs-generator.sh.in
+@@ -0,0 +1,39 @@
++#!/bin/bash
++
++GENERATOR_DIR="$1"
++[ -z "$GENERATOR_DIR" ] && 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"
++
++[ -z "$root" ] && root=$(getarg root=)
++[ -z "$rootfstype" ] && rootfstype=$(getarg rootfstype=)
++[ -z "$rootflags" ] && rootflags=$(getarg rootflags=)
++
++[ "${root##zfs:}" = "${root}" -a "${root##ZFS=}" = "${root}" -a "$rootfstype" != "zfs" ] && exit 0
++
++rootfstype=zfs
++if echo "${rootflags}" | grep -q zfsutil ; then
++ true
++else
++ rootflags=zfsutil
++fi
++
++root="${root##zfs:}"
++root="${root##ZFS=}"
++
++[ -d "$GENERATOR_DIR" ] || mkdir "$GENERATOR_DIR"
++[ -d "$GENERATOR_DIR/sysroot.mount.d" ] || mkdir "$GENERATOR_DIR/sysroot.mount.d"
++
++{
++ echo "[Unit]"
++ 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"
+diff --git a/contrib/dracut/Makefile.am b/contrib/dracut/Makefile.am
+index 35b88c3..1065e5e 100644
+--- a/contrib/dracut/Makefile.am
++++ b/contrib/dracut/Makefile.am
+@@ -1,3 +1,3 @@
+-SUBDIRS = 90zfs
++SUBDIRS = 02zfsexpandknowledge 90zfs
+
+ EXTRA_DIST = README.dracut.markdown
+--
+2.1.4
+