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
module-setup.sh
mount-zfs.sh
parse-zfs.sh
+zfs-lib.sh
$(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' \
#!/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
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
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
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"
}
#!/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
# 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
# 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
--- /dev/null
+#!/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}
+}
* `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`
---------------