]> granicus.if.org Git - zfs/commitdiff
fix booting via dracut generated initramfs
authorMatthew Thode <mthode@mthode.org>
Wed, 30 Mar 2016 23:59:15 +0000 (18:59 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 25 Apr 2016 15:51:38 +0000 (08:51 -0700)
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
contrib/dracut/02zfsexpandknowledge/Makefile.am [new file with mode: 0644]
contrib/dracut/02zfsexpandknowledge/module-setup.sh.in [new file with mode: 0755]
contrib/dracut/90zfs/Makefile.am
contrib/dracut/90zfs/module-setup.sh.in
contrib/dracut/90zfs/zfs-generator.sh.in [new file with mode: 0644]
contrib/dracut/Makefile.am

index 41cd00758119d2a8ae7032c25896314ed61a6622..5037ccbe7361eb9ec623d28ac4b98916342b78f0 100644 (file)
@@ -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 (file)
index 0000000..0a2170b
--- /dev/null
@@ -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 (executable)
index 0000000..830ee42
--- /dev/null
@@ -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
+}
index b778a274486e68b73e9278710b68d79449c9ddc2..f81d6c3575b37479e7f76a09ba9947769ae159be 100644 (file)
@@ -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::
index 9eb9f576521a1b7a71ab2c88e6c2b98a43e569f7..301375a5b37d39e23a2792f05213246408b29730 100755 (executable)
@@ -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 (file)
index 0000000..0e0664d
--- /dev/null
@@ -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"
index 35b88c36fbc0db018a698d775fae7f77402cc4db..1065e5e94f0ebdce83ee52f3d3ce04f2949f3225 100644 (file)
@@ -1,3 +1,3 @@
-SUBDIRS = 90zfs
+SUBDIRS = 02zfsexpandknowledge 90zfs
 
 EXTRA_DIST = README.dracut.markdown