From fad1a790988a2a609d655f59b58dbc1fe99e1c3e Mon Sep 17 00:00:00 2001 From: Zachary Bedell Date: Mon, 4 Jul 2011 13:25:31 -0400 Subject: [PATCH] Update Dracut module for Dracut-010 & fix race conditions that caused boot to fail on MP systems. Add support for zfs_force flag & parsing of spl_hostid from kernel command line. --- dracut/90zfs/90-zfs.rules | 3 ++ dracut/90zfs/Makefile.am | 5 +-- dracut/90zfs/Makefile.in | 5 +-- dracut/90zfs/check | 10 ------ dracut/90zfs/install | 17 --------- dracut/90zfs/installkernel | 10 ------ dracut/90zfs/module-setup.sh | 46 ++++++++++++++++++++++++ dracut/90zfs/mount-zfs.sh | 69 ++++++++++++++++++++++++++++++------ dracut/90zfs/parse-zfs.sh | 64 ++++++++++++++++++++++----------- dracut/90zfs/zfs-genrules.sh | 12 ------- 10 files changed, 154 insertions(+), 87 deletions(-) delete mode 100755 dracut/90zfs/check delete mode 100755 dracut/90zfs/install delete mode 100755 dracut/90zfs/installkernel create mode 100755 dracut/90zfs/module-setup.sh delete mode 100755 dracut/90zfs/zfs-genrules.sh diff --git a/dracut/90zfs/90-zfs.rules b/dracut/90zfs/90-zfs.rules index 918d726d7461..52e1d639303e 100644 --- a/dracut/90zfs/90-zfs.rules +++ b/dracut/90zfs/90-zfs.rules @@ -4,4 +4,7 @@ ACTION!="add|change", GOTO="zfs_end" ENV{ID_FS_TYPE}=="zfs", RUN+="/sbin/modprobe zfs" ENV{ID_FS_TYPE}=="zfs_member", RUN+="/sbin/modprobe zfs" +KERNEL=="null", SYMLINK+="root" +SYMLINK=="null", SYMLINK+="root" + LABEL="zfs_end" diff --git a/dracut/90zfs/Makefile.am b/dracut/90zfs/Makefile.am index e2e3ff8cbd69..605654c233b0 100644 --- a/dracut/90zfs/Makefile.am +++ b/dracut/90zfs/Makefile.am @@ -1,11 +1,8 @@ pkgdracutdir = $(datadir)/dracut/modules.d/90zfs dist_pkgdracut_SCRIPTS = \ $(top_srcdir)/dracut/90zfs/90-zfs.rules \ - $(top_srcdir)/dracut/90zfs/check \ - $(top_srcdir)/dracut/90zfs/install \ - $(top_srcdir)/dracut/90zfs/installkernel \ + $(top_srcdir)/dracut/90zfs/module-setup.sh \ $(top_srcdir)/dracut/90zfs/mount-zfs.sh \ - $(top_srcdir)/dracut/90zfs/zfs-genrules.sh \ $(top_srcdir)/dracut/90zfs/parse-zfs.sh all: diff --git a/dracut/90zfs/Makefile.in b/dracut/90zfs/Makefile.in index 49ed262641f6..aa40fe5eff1d 100644 --- a/dracut/90zfs/Makefile.in +++ b/dracut/90zfs/Makefile.in @@ -289,11 +289,8 @@ top_srcdir = @top_srcdir@ pkgdracutdir = $(datadir)/dracut/modules.d/90zfs dist_pkgdracut_SCRIPTS = \ $(top_srcdir)/dracut/90zfs/90-zfs.rules \ - $(top_srcdir)/dracut/90zfs/check \ - $(top_srcdir)/dracut/90zfs/install \ - $(top_srcdir)/dracut/90zfs/installkernel \ + $(top_srcdir)/dracut/90zfs/module-setup.sh \ $(top_srcdir)/dracut/90zfs/mount-zfs.sh \ - $(top_srcdir)/dracut/90zfs/zfs-genrules.sh \ $(top_srcdir)/dracut/90zfs/parse-zfs.sh all: all-am diff --git a/dracut/90zfs/check b/dracut/90zfs/check deleted file mode 100755 index ac4006b8627e..000000000000 --- a/dracut/90zfs/check +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# We depend on udev-rules being loaded -[ "$1" = "-d" ] && exit 0 - -# Verify the zfs tool chain -which zpool >/dev/null 2>&1 || exit 1 -which zfs >/dev/null 2>&1 || exit 1 - -exit 0 diff --git a/dracut/90zfs/install b/dracut/90zfs/install deleted file mode 100755 index 5be97686038f..000000000000 --- a/dracut/90zfs/install +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -inst_rules "$moddir/90-zfs.rules" -inst_rules /etc/udev/rules.d/60-zpool.rules -inst_rules /etc/udev/rules.d/60-zvol.rules -inst /etc/zfs/zdev.conf -inst /etc/hostid -dracut_install zfs -dracut_install zpool -dracut_install zpool_layout -dracut_install zpool_id -dracut_install zvol_id -dracut_install mount.zfs -dracut_install hostid -inst_hook cmdline 95 "$moddir/parse-zfs.sh" -inst_hook mount 98 "$moddir/mount-zfs.sh" -inst_hook pre-udev 29 "$moddir/zfs-genrules.sh" diff --git a/dracut/90zfs/installkernel b/dracut/90zfs/installkernel deleted file mode 100755 index c3fa7de17ef7..000000000000 --- a/dracut/90zfs/installkernel +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -instmods zfs -instmods zcommon -instmods znvpair -instmods zavl -instmods zunicode -instmods spl -instmods zlib_deflate -instmods zlib_inflate diff --git a/dracut/90zfs/module-setup.sh b/dracut/90zfs/module-setup.sh new file mode 100755 index 000000000000..1816b38d7a4d --- /dev/null +++ b/dracut/90zfs/module-setup.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +check() { + # We depend on udev-rules being loaded + [ "$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 + + return 0 +} + +depends() { + echo udev-rules + return 0 +} + +installkernel() { + instmods zfs + instmods zcommon + instmods znvpair + instmods zavl + instmods zunicode + instmods spl + instmods zlib_deflate + instmods zlib_inflate +} + +install() { + inst_rules "$moddir/90-zfs.rules" + inst_rules /etc/udev/rules.d/60-zpool.rules + inst_rules /etc/udev/rules.d/60-zvol.rules + inst /etc/zfs/zdev.conf + inst /etc/zfs/zpool.cache + inst /etc/hostid + dracut_install zfs + dracut_install zpool + dracut_install zpool_layout + dracut_install zpool_id + dracut_install zvol_id + dracut_install mount.zfs + dracut_install hostid + inst_hook cmdline 95 "$moddir/parse-zfs.sh" + inst_hook mount 98 "$moddir/mount-zfs.sh" +} diff --git a/dracut/90zfs/mount-zfs.sh b/dracut/90zfs/mount-zfs.sh index b4a4de6ff013..ce5f4b902851 100755 --- a/dracut/90zfs/mount-zfs.sh +++ b/dracut/90zfs/mount-zfs.sh @@ -2,15 +2,64 @@ . /lib/dracut-lib.sh -if [ "$rootfs" = "zfs" ]; then - zfsrootfs=`echo "$root" | sed 's|^zfs:||'` - zfspool=`echo "$zfsrootfs" | sed 's|/.*||g'` - zpool import -N "$zfspool" - mount -o zfsutil -t "$rootfs" "$zfsrootfs" "$NEWROOT" - if [ "$?" = "0" ] - then - ROOTFS_MOUNTED=yes +ZPOOL_FORCE="" +if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then + warn "ZFS: Will force-import pools if necessary." + ZPOOL_FORCE="-f" +fi + +case "$root" in + zfs:*) + # We have ZFS modules loaded, so we're able to import pools now. + if [ "$root" = "zfs:AUTO" ] ; then + # Need to parse bootfs attribute + info "ZFS: Attempting to detect root from imported ZFS pools." + + # Might be imported by the kernel module, so try searching before we import anything. + zfsbootfs=`zpool list -H -o bootfs | sed 'q'` + if [ "$zfsbootfs" = "" ] ; then + # Not there, so we need to import everything. + info "ZFS: Attempting to import additional pools." + zpool import -N -a ${ZPOOL_FORCE} + zfsbootfs=`zpool list -H -o bootfs | sed 'q'` + if [ "$zfsbootfs" = "" ] ; then + rootok=0 + pool="" + + warn "ZFS: No bootfs attribute found in importable pools." + + # Re-export everything since we're not prepared to take responsibility for them + zpool list -H | while read fs rest ; do + zpool export "$fs" + done + + return 1 + fi + fi + info "ZFS: Using ${zfsbootfs} as root." else - mount -t "$rootfs" "$zfsrootfs" "$NEWROOT" && ROOTFS_MOUNTED=yes + # Should have an explicit pool set, so just import it and we're done. + zfsbootfs="${root#zfs:}" + pool="${zfsbootfs%%/*}" + if ! zpool list -H $pool > /dev/null ; then + # pool wasn't imported automatically by the kernel module, so try it manually. + info "ZFS: Importing pool ${pool}..." + if ! zpool import -N ${ZPOOL_FORCE} $pool ; then + warn "ZFS: Unable to import pool ${pool}." + rootok=0 + + return 1 + fi + fi fi -fi + + # Above should have left our rpool imported and pool/dataset in $root. + # We need zfsutil for non-legacy mounts and not for legacy mounts. + mountpoint=`zfs get -H -o value mountpoint $zfsbootfs` + if [ "$mountpoint" = "legacy" ] ; then + mount -t zfs "$zfsbootfs" "$NEWROOT" && ROOTFS_MOUNTED=yes + else + mount -o zfsutil -t zfs "$zfsbootfs" "$NEWROOT" && ROOTFS_MOUNTED=yes + fi + ;; +esac diff --git a/dracut/90zfs/parse-zfs.sh b/dracut/90zfs/parse-zfs.sh index ef3d058ac2b4..8b88ca689a0b 100755 --- a/dracut/90zfs/parse-zfs.sh +++ b/dracut/90zfs/parse-zfs.sh @@ -1,23 +1,47 @@ +#!/bin/sh + +. /lib/dracut-lib.sh + +# Let the command line override our host id. +spl_hostid=`getarg spl_hostid=` +if [ "${spl_hostid}" != "" ] ; then + info "ZFS: Using hostid from command line: ${spl_hostid}" + echo "${spl_hostid}" > /etc/hostid +elif [ -f /etc/hostid ] ; then + info "ZFS: Using hostid from /etc/hostid: `cat /etc/hostid`" +else + warn "ZFS: No hostid found on kernel command line or /etc/hostid. ZFS pools may not import correctly." +fi + case "$root" in - zfs:FILESYSTEM=*|FILESYSTEM=*) - root="${root#zfs:}" - root="zfs:${root#FILESYSTEM=}" - rootfs="zfs" - rootok=1 ;; - zfs:ZFS=*|ZFS=*) - root="${root#zfs:}" - root="zfs:${root#ZFS=}" - rootfs="zfs" - rootok=1 ;; + ""|zfs|zfs:) + # We'll take root unset, root=zfs, or root=zfs: + # No root set, so we want to read the bootfs attribute. We can't do that until udev settles, + # so we'll set dummy values and hope for the best later on. + root="zfs:AUTO" + rootok=1 + + info "ZFS: Enabling autodetection of bootfs after udev settles." + ;; + + ZFS\=*|zfs:*|zfs:FILESYSTEM\=*|FILESYSTEM\=*) + # root is explicit ZFS root. Parse it now. + # We can handle a root=... param in any of the following formats: + # root=ZFS=rpool/ROOT + # root=zfs:rpool/ROOT + # root=zfs:FILESYSTEM=rpool/ROOT + # root=FILESYSTEM=rpool/ROOT + + # Strip down to just the pool/fs + root="${root#zfs:}" + root="${root#FILESYSTEM=}" + root="zfs:${root#ZFS=}" + rootok=1 + + info "ZFS: Set ${root} as bootfs." + ;; esac -if [ "$rootok" != "1" ] ; then - zpool import -aN - zfsbootfs=`zpool list -H -o bootfs | grep -v ^-$ -m 1` - if [ -n "$zfsbootfs" ] ; then - root="zfs:$zfsbootfs" - rootfs="zfs" - rootok=1 - fi - zpool list -H | while read fs rest ; do zpool export "$fs" ; done -fi +# Make sure Dracut is happy that we have a root and will wait for ZFS modules to settle before mounting. +ln -s /dev/null /dev/root 2>/dev/null +echo '[ -e /dev/zfs ]' > $hookdir/initqueue/finished/zfs.sh diff --git a/dracut/90zfs/zfs-genrules.sh b/dracut/90zfs/zfs-genrules.sh deleted file mode 100755 index ffbd51ff1179..000000000000 --- a/dracut/90zfs/zfs-genrules.sh +++ /dev/null @@ -1,12 +0,0 @@ -if [ "${root%%:*}" = "zfs" ]; then - [ -d /dev/.udev/rules.d ] || mkdir -p /dev/.udev/rules.d - { - printf 'KERNEL=="%s", SYMLINK+="root"\n' null - printf 'SYMLINK=="%s", SYMLINK+="root"\n' null - } >> /dev/.udev/rules.d/99-zfs.rules - - printf '[ -e "%s" ] && { ln -s "%s" /dev/root 2>/dev/null; rm "$job"; }\n' \ - "/dev/null" "/dev/null" >> /initqueue-settled/zfssymlink.sh - - echo '[ -e /dev/root ]' > /initqueue-finished/zfs.sh -fi