From: Sören Tempel Date: Sun, 15 Feb 2015 19:28:42 +0000 (+0100) Subject: Refactor dracut module X-Git-Tag: zfs-0.6.5~116 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eda3d4e1de94cd3a9247bb90a64413a89e736847;p=zfs Refactor dracut module Provide '/lib/dracut-zfs-lib.sh' with utility functions. Signed-off-by: Sören Tempel Signed-off-by: Brian Behlendorf Issue #3109 --- diff --git a/dracut/90zfs/.gitignore b/dracut/90zfs/.gitignore index 72a710a0e..9502be985 100644 --- a/dracut/90zfs/.gitignore +++ b/dracut/90zfs/.gitignore @@ -2,3 +2,4 @@ export-zfs.sh module-setup.sh mount-zfs.sh parse-zfs.sh +zfs-lib.sh diff --git a/dracut/90zfs/Makefile.am b/dracut/90zfs/Makefile.am index 2d1360ade..650953c1b 100644 --- a/dracut/90zfs/Makefile.am +++ b/dracut/90zfs/Makefile.am @@ -3,13 +3,15 @@ pkgdracut_SCRIPTS = \ $(top_srcdir)/dracut/90zfs/export-zfs.sh \ $(top_srcdir)/dracut/90zfs/module-setup.sh \ $(top_srcdir)/dracut/90zfs/mount-zfs.sh \ - $(top_srcdir)/dracut/90zfs/parse-zfs.sh + $(top_srcdir)/dracut/90zfs/parse-zfs.sh \ + $(top_srcdir)/dracut/90zfs/zfs-lib.sh EXTRA_DIST = \ $(top_srcdir)/dracut/90zfs/export-zfs.sh.in \ $(top_srcdir)/dracut/90zfs/module-setup.sh.in \ $(top_srcdir)/dracut/90zfs/mount-zfs.sh.in \ - $(top_srcdir)/dracut/90zfs/parse-zfs.sh.in + $(top_srcdir)/dracut/90zfs/parse-zfs.sh.in \ + $(top_srcdir)/dracut/90zfs/zfs-lib.sh.in $(pkgdracut_SCRIPTS): -$(SED) -e 's,@bindir\@,$(bindir),g' \ diff --git a/dracut/90zfs/export-zfs.sh.in b/dracut/90zfs/export-zfs.sh.in index 6382d762a..393753fbf 100755 --- a/dracut/90zfs/export-zfs.sh.in +++ b/dracut/90zfs/export-zfs.sh.in @@ -1,35 +1,29 @@ #!/bin/sh +. /lib/dracut-zfs-lib.sh + _do_zpool_export() { local ret=0 - local final=$1 - local force - local OLDIFS="$IFS" - local NEWLINE=" -" + local final="${1}" + local opts="" - if [ "x$final" != "x" ]; then - force="-f" + if [ "x${final}" != "x" ]; then + opts="-f" fi - info "Exporting ZFS storage pools" - # Change IFS to allow for blanks in pool names. - IFS="$NEWLINE" - for fs in `zpool list -H -o name` ; do - zpool export $force "$fs" || ret=$? - done - IFS="$OLDIFS" + info "Exporting ZFS storage pools." + export_all ${opts} || ret=$? - if [ "x$final" != "x" ]; then + if [ "x${final}" != "x" ]; then info "zpool list" zpool list 2>&1 | vinfo fi - return $ret + return ${ret} } if command -v zpool >/dev/null; then - _do_zpool_export $1 + _do_zpool_export "${1}" else : fi diff --git a/dracut/90zfs/module-setup.sh.in b/dracut/90zfs/module-setup.sh.in index 81401f2b5..9eb9f5765 100755 --- a/dracut/90zfs/module-setup.sh.in +++ b/dracut/90zfs/module-setup.sh.in @@ -2,7 +2,7 @@ check() { # We depend on udev-rules being loaded - [ "$1" = "-d" ] && return 0 + [ "${1}" = "-d" ] && return 0 # Verify the zfs tool chain which zpool >/dev/null 2>&1 || return 1 @@ -39,10 +39,11 @@ install() { dracut_install hostid dracut_install awk dracut_install head - inst_hook cmdline 95 "$moddir/parse-zfs.sh" - inst_hook mount 98 "$moddir/mount-zfs.sh" - inst_hook shutdown 30 "$moddir/export-zfs.sh" + inst_hook cmdline 95 "${moddir}/parse-zfs.sh" + inst_hook mount 98 "${moddir}/mount-zfs.sh" + 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 fi @@ -56,5 +57,5 @@ install() { BB=`hostid | cut -b 3,4` CC=`hostid | cut -b 5,6` DD=`hostid | cut -b 7,8` - printf "\x$DD\x$CC\x$BB\x$AA" > "$initdir/etc/hostid" + printf "\x${DD}\x${CC}\x${BB}\x${AA}" > "${initdir}/etc/hostid" } diff --git a/dracut/90zfs/mount-zfs.sh.in b/dracut/90zfs/mount-zfs.sh.in index 8237d76f2..47c01d14c 100755 --- a/dracut/90zfs/mount-zfs.sh.in +++ b/dracut/90zfs/mount-zfs.sh.in @@ -1,82 +1,45 @@ #!/bin/sh . /lib/dracut-lib.sh +. /lib/dracut-zfs-lib.sh -ZPOOL_FORCE="" -OLDIFS="$IFS" -NEWLINE=" -" +ZFS_DATASET="" +ZFS_POOL="" -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:*) ;; + *) return ;; +esac # Delay until all required block devices are present. udevadm settle -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 -n '/^-$/ !p' | sed 'q'` - if [ $? -ne 0 ] || [ -z "$zfsbootfs" ] || \ - [ "$zfsbootfs" = "no pools available" ] ; 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 -n '/^-$/ !p' | sed 'q'` - if [ $? -ne 0 ] || [ -z "$zfsbootfs" ] || \ - [ "$zfsbootfs" = "no pools available" ] ; 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. - # Change IFS to allow for blanks in pool names. - IFS="$NEWLINE" - for fs in `zpool list -H -o name` ; do - zpool export "$fs" - done - IFS="$OLDIFS" - - return 1 - fi - fi - info "ZFS: Using ${zfsbootfs} as root." - else - # 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 +if [ "${root}" = "zfs:AUTO" ] ; then + ZFS_DATASET="$(find_bootfs)" + if [ $? -ne 0 ] ; then + zpool import -N -a ${ZPOOL_IMPORT_OPTS} + ZFS_DATASET="$(find_bootfs)" + if [ $? -ne 0 ] ; then + warn "ZFS: No bootfs attribute found in importable pools." + export_all + + rootok=0 + return 1 fi + fi + info "ZFS: Using ${ZFS_DATASET} as root." +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 +ZFS_DATASET="${ZFS_DATASET:-${root#zfs:}}" +ZFS_POOL="${ZFS_DATASET%%/*}" - need_shutdown - ;; -esac +if import_pool "${ZFS_POOL}" ; then + info "ZFS: Mounting dataset ${ZFS_DATASET}..." + if mount_dataset "${ZFS_DATASET}" ; then + ROOTFS_MOUNTED=yes + return 0 + fi +fi + +rootok=0 +need_shutdown diff --git a/dracut/90zfs/parse-zfs.sh.in b/dracut/90zfs/parse-zfs.sh.in index f45a629f3..c305c7821 100755 --- a/dracut/90zfs/parse-zfs.sh.in +++ b/dracut/90zfs/parse-zfs.sh.in @@ -4,22 +4,22 @@ # Let the command line override our host id. spl_hostid=`getarg spl_hostid=` -if [ "${spl_hostid}" != "" ] ; then +if [ -n "${spl_hostid}" ] ; then info "ZFS: Using hostid from command line: ${spl_hostid}" AA=`echo ${spl_hostid} | cut -b 1,2` BB=`echo ${spl_hostid} | cut -b 3,4` CC=`echo ${spl_hostid} | cut -b 5,6` DD=`echo ${spl_hostid} | cut -b 7,8` - printf "\x$DD\x$CC\x$BB\x$AA" >/etc/hostid -elif [ -f /etc/hostid ] ; then + printf "\x${DD}\x${CC}\x${BB}\x${AA}" >/etc/hostid +elif [ -f "/etc/hostid" ] ; then info "ZFS: Using hostid from /etc/hostid: `hostid`" else - warn "ZFS: No hostid found on kernel command line or /etc/hostid. " + warn "ZFS: No hostid found on kernel command line or /etc/hostid." warn "ZFS: Pools may not import correctly." fi wait_for_zfs=0 -case "$root" in +case "${root}" in ""|zfs|zfs:) # We'll take root unset, root=zfs, or root=zfs: # No root set, so we want to read the bootfs attribute. We @@ -55,5 +55,5 @@ esac # modules to settle before mounting. if [ ${wait_for_zfs} -eq 1 ]; then ln -s /dev/null /dev/root 2>/dev/null - echo '[ -e /dev/zfs ]' > $hookdir/initqueue/finished/zfs.sh + echo '[ -e /dev/zfs ]' > "${hookdir}/initqueue/finished/zfs.sh" fi diff --git a/dracut/90zfs/zfs-lib.sh.in b/dracut/90zfs/zfs-lib.sh.in new file mode 100755 index 000000000..a6ed4c3f4 --- /dev/null +++ b/dracut/90zfs/zfs-lib.sh.in @@ -0,0 +1,87 @@ +#!/bin/sh + +. /lib/dracut-lib.sh + +OLDIFS="${IFS}" +NEWLINE=" +" + +ZPOOL_IMPORT_OPTS="" +if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then + warn "ZFS: Will force-import pools if necessary." + ZPOOL_IMPORT_OPTS="${ZPOOL_IMPORT_OPTS} -f" +fi + +# find_bootfs +# returns the first dataset with the bootfs attribute. +find_bootfs() { + IFS="${NEWLINE}" + for dataset in $(zpool list -H -o bootfs); do + case "${dataset}" in + "" | "-") + continue + ;; + "no pools available") + IFS="${OLDIFS}" + return 1 + ;; + *) + IFS="${OLDIFS}" + echo "${dataset}" + return 0 + ;; + esac + done + + IFS="${OLDIFS}" + return 1 +} + +# import_pool POOL +# imports the given zfs pool if it isn't imported already. +import_pool() { + local pool="${1}" + + if ! zpool list -H "${pool}" 2>&1 > /dev/null ; then + info "ZFS: Importing pool ${pool}..." + if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${pool}" ; then + warn "ZFS: Unable to import pool ${pool}" + return 1 + fi + fi + + return 0 +} + +# mount_dataset DATASET +# mounts the given zfs dataset. +mount_dataset() { + local dataset="${1}" + local mountpoint="$(zfs get -H -o value mountpoint "${dataset}")" + + # We need zfsutil for non-legacy mounts and not for legacy mounts. + if [ "${mountpoint}" = "legacy" ] ; then + mount -t zfs "${dataset}" "${NEWROOT}" + else + mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}" + fi + + return $? +} + +# export_all OPTS +# exports all imported zfs pools. +export_all() { + local opts="${1}" + local ret=0 + + IFS="${NEWLINE}" + for pool in `zpool list -H -o name` ; do + if zpool list -H "${pool}" 2>&1 > /dev/null ; then + zpool export "${pool}" ${opts} || ret=$? + fi + done + IFS="${OLDIFS}" + + return ${ret} +} diff --git a/dracut/README.dracut.markdown b/dracut/README.dracut.markdown index 27e94fff9..e07326493 100644 --- a/dracut/README.dracut.markdown +++ b/dracut/README.dracut.markdown @@ -80,6 +80,8 @@ to mount the root dataset. * `export-zfs.sh`: Run on shutdown after dracut has restored the initramfs and pivoted to it, allowing for a clean unmount and export of the ZFS root. +* `zfs-lib.sh`: Utility functions used by the other files. + `module-setup.sh` ---------------