aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/dracut
diff options
context:
space:
mode:
authorMatthew Thode <[email protected]>2016-03-30 18:59:15 -0500
committerBrian Behlendorf <[email protected]>2016-04-25 08:51:38 -0700
commita5a370227eb0a3daf8992a38920d54eb3b7b3c25 (patch)
treecc85181222f7cd64ff79c9eae7013588730977c2 /contrib/dracut
parent232604b58e8579501c5a260ad3a7b71a239dd546 (diff)
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) <[email protected]> Signed-off-by: Matthew Thode <[email protected]> Closes #3605 Closes #4478
Diffstat (limited to 'contrib/dracut')
-rw-r--r--contrib/dracut/02zfsexpandknowledge/Makefile.am22
-rwxr-xr-xcontrib/dracut/02zfsexpandknowledge/module-setup.sh.in132
-rw-r--r--contrib/dracut/90zfs/Makefile.am3
-rwxr-xr-xcontrib/dracut/90zfs/module-setup.sh.in19
-rw-r--r--contrib/dracut/90zfs/zfs-generator.sh.in39
-rw-r--r--contrib/dracut/Makefile.am2
6 files changed, 215 insertions, 2 deletions
diff --git a/contrib/dracut/02zfsexpandknowledge/Makefile.am b/contrib/dracut/02zfsexpandknowledge/Makefile.am
new file mode 100644
index 000000000..0a2170bfc
--- /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/[email protected]" >'$@'
+
+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 000000000..830ee42f6
--- /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 b778a2744..f81d6c357 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/[email protected]" >'$@'
distclean-local::
diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in
index 9eb9f5765..301375a5b 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 000000000..0e0664d0a
--- /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 35b88c36f..1065e5e94 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