Refactor dracut module

Provide '/lib/dracut-zfs-lib.sh' with utility functions.

Signed-off-by: Sören Tempel <soeren+git@soeren-tempel.net>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #3109
This commit is contained in:
Sören Tempel 2015-02-15 20:28:42 +01:00 committed by Brian Behlendorf
parent 036391c980
commit eda3d4e1de
8 changed files with 149 additions and 99 deletions

View File

@ -2,3 +2,4 @@ export-zfs.sh
module-setup.sh module-setup.sh
mount-zfs.sh mount-zfs.sh
parse-zfs.sh parse-zfs.sh
zfs-lib.sh

View File

@ -3,13 +3,15 @@ pkgdracut_SCRIPTS = \
$(top_srcdir)/dracut/90zfs/export-zfs.sh \ $(top_srcdir)/dracut/90zfs/export-zfs.sh \
$(top_srcdir)/dracut/90zfs/module-setup.sh \ $(top_srcdir)/dracut/90zfs/module-setup.sh \
$(top_srcdir)/dracut/90zfs/mount-zfs.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 = \ EXTRA_DIST = \
$(top_srcdir)/dracut/90zfs/export-zfs.sh.in \ $(top_srcdir)/dracut/90zfs/export-zfs.sh.in \
$(top_srcdir)/dracut/90zfs/module-setup.sh.in \ $(top_srcdir)/dracut/90zfs/module-setup.sh.in \
$(top_srcdir)/dracut/90zfs/mount-zfs.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): $(pkgdracut_SCRIPTS):
-$(SED) -e 's,@bindir\@,$(bindir),g' \ -$(SED) -e 's,@bindir\@,$(bindir),g' \

View File

@ -1,35 +1,29 @@
#!/bin/sh #!/bin/sh
. /lib/dracut-zfs-lib.sh
_do_zpool_export() { _do_zpool_export() {
local ret=0 local ret=0
local final=$1 local final="${1}"
local force local opts=""
local OLDIFS="$IFS"
local NEWLINE="
"
if [ "x$final" != "x" ]; then if [ "x${final}" != "x" ]; then
force="-f" opts="-f"
fi fi
info "Exporting ZFS storage pools" info "Exporting ZFS storage pools."
# Change IFS to allow for blanks in pool names. export_all ${opts} || ret=$?
IFS="$NEWLINE"
for fs in `zpool list -H -o name` ; do
zpool export $force "$fs" || ret=$?
done
IFS="$OLDIFS"
if [ "x$final" != "x" ]; then if [ "x${final}" != "x" ]; then
info "zpool list" info "zpool list"
zpool list 2>&1 | vinfo zpool list 2>&1 | vinfo
fi fi
return $ret return ${ret}
} }
if command -v zpool >/dev/null; then if command -v zpool >/dev/null; then
_do_zpool_export $1 _do_zpool_export "${1}"
else else
: :
fi fi

View File

@ -2,7 +2,7 @@
check() { check() {
# We depend on udev-rules being loaded # We depend on udev-rules being loaded
[ "$1" = "-d" ] && return 0 [ "${1}" = "-d" ] && return 0
# Verify the zfs tool chain # Verify the zfs tool chain
which zpool >/dev/null 2>&1 || return 1 which zpool >/dev/null 2>&1 || return 1
@ -39,10 +39,11 @@ install() {
dracut_install hostid dracut_install hostid
dracut_install awk dracut_install awk
dracut_install head dracut_install head
inst_hook cmdline 95 "$moddir/parse-zfs.sh" inst_hook cmdline 95 "${moddir}/parse-zfs.sh"
inst_hook mount 98 "$moddir/mount-zfs.sh" inst_hook mount 98 "${moddir}/mount-zfs.sh"
inst_hook shutdown 30 "$moddir/export-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 if [ -e @sysconfdir@/zfs/zpool.cache ]; then
inst @sysconfdir@/zfs/zpool.cache inst @sysconfdir@/zfs/zpool.cache
fi fi
@ -56,5 +57,5 @@ install() {
BB=`hostid | cut -b 3,4` BB=`hostid | cut -b 3,4`
CC=`hostid | cut -b 5,6` CC=`hostid | cut -b 5,6`
DD=`hostid | cut -b 7,8` 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"
} }

View File

@ -1,82 +1,45 @@
#!/bin/sh #!/bin/sh
. /lib/dracut-lib.sh . /lib/dracut-lib.sh
. /lib/dracut-zfs-lib.sh
ZPOOL_FORCE="" ZFS_DATASET=""
OLDIFS="$IFS" ZFS_POOL=""
NEWLINE="
"
if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then case "${root}" in
warn "ZFS: Will force-import pools if necessary." zfs:*) ;;
ZPOOL_FORCE="-f" *) return ;;
fi esac
# Delay until all required block devices are present. # Delay until all required block devices are present.
udevadm settle udevadm settle
case "$root" in if [ "${root}" = "zfs:AUTO" ] ; then
zfs:*) ZFS_DATASET="$(find_bootfs)"
# We have ZFS modules loaded, so we're able to import pools now. if [ $? -ne 0 ] ; then
if [ "$root" = "zfs:AUTO" ] ; then zpool import -N -a ${ZPOOL_IMPORT_OPTS}
# Need to parse bootfs attribute ZFS_DATASET="$(find_bootfs)"
info "ZFS: Attempting to detect root from imported ZFS pools." if [ $? -ne 0 ] ; then
warn "ZFS: No bootfs attribute found in importable pools."
export_all
# Might be imported by the kernel module, so try searching before rootok=0
# we import anything. return 1
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
fi fi
fi
info "ZFS: Using ${ZFS_DATASET} as root."
fi
# Above should have left our rpool imported and pool/dataset in $root. ZFS_DATASET="${ZFS_DATASET:-${root#zfs:}}"
# We need zfsutil for non-legacy mounts and not for legacy mounts. ZFS_POOL="${ZFS_DATASET%%/*}"
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
need_shutdown if import_pool "${ZFS_POOL}" ; then
;; info "ZFS: Mounting dataset ${ZFS_DATASET}..."
esac if mount_dataset "${ZFS_DATASET}" ; then
ROOTFS_MOUNTED=yes
return 0
fi
fi
rootok=0
need_shutdown

View File

@ -4,22 +4,22 @@
# Let the command line override our host id. # Let the command line override our host id.
spl_hostid=`getarg spl_hostid=` spl_hostid=`getarg spl_hostid=`
if [ "${spl_hostid}" != "" ] ; then if [ -n "${spl_hostid}" ] ; then
info "ZFS: Using hostid from command line: ${spl_hostid}" info "ZFS: Using hostid from command line: ${spl_hostid}"
AA=`echo ${spl_hostid} | cut -b 1,2` AA=`echo ${spl_hostid} | cut -b 1,2`
BB=`echo ${spl_hostid} | cut -b 3,4` BB=`echo ${spl_hostid} | cut -b 3,4`
CC=`echo ${spl_hostid} | cut -b 5,6` CC=`echo ${spl_hostid} | cut -b 5,6`
DD=`echo ${spl_hostid} | cut -b 7,8` DD=`echo ${spl_hostid} | cut -b 7,8`
printf "\x$DD\x$CC\x$BB\x$AA" >/etc/hostid printf "\x${DD}\x${CC}\x${BB}\x${AA}" >/etc/hostid
elif [ -f /etc/hostid ] ; then elif [ -f "/etc/hostid" ] ; then
info "ZFS: Using hostid from /etc/hostid: `hostid`" info "ZFS: Using hostid from /etc/hostid: `hostid`"
else 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." warn "ZFS: Pools may not import correctly."
fi fi
wait_for_zfs=0 wait_for_zfs=0
case "$root" in case "${root}" in
""|zfs|zfs:) ""|zfs|zfs:)
# We'll take root unset, root=zfs, or root=zfs: # We'll take root unset, root=zfs, or root=zfs:
# No root set, so we want to read the bootfs attribute. We # No root set, so we want to read the bootfs attribute. We
@ -55,5 +55,5 @@ esac
# modules to settle before mounting. # modules to settle before mounting.
if [ ${wait_for_zfs} -eq 1 ]; then if [ ${wait_for_zfs} -eq 1 ]; then
ln -s /dev/null /dev/root 2>/dev/null 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 fi

87
dracut/90zfs/zfs-lib.sh.in Executable file
View File

@ -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}
}

View File

@ -80,6 +80,8 @@ to mount the root dataset.
* `export-zfs.sh`: Run on shutdown after dracut has restored the initramfs * `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. 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` `module-setup.sh`
--------------- ---------------