Skip to content

Commit

Permalink
Initramfs scripts for ZoL.
Browse files Browse the repository at this point in the history
* Put in /usr/share/initramfs-tools/ or /etc/initramfs-tools/.
* With pull request openzfs#1476 (not yet merged) comes a verbose warning
  if /usr/bin/net doesn't exist or isn't executable. Just create
  a dummy...
* If user haven't specified pool, but bootfs then use the first part
  of the bootfs path as pool name.
* Add support for booting of a ZFS snapshot.
  Do this by cloning the snapshot into a dataset. If this the resulting
  dataset already exists, destroy it. Then set mountpoint=/ on that
  dataset and mount it on root.
  + If snapshot does not exist, use base dataset (the part before '@')
    as boot filesystem instead.
* Add support for more kernel command line arguments (ideas taken from
  the Fedora/Redhat dracut script):
  + (zfs_force|zfs.force|zfsforce)=(on|yes|1) (ignore case).
  + root=zfs:AUTO => try to find rootfs automatically.
  + root=zfs:<dataset>
  + root=ZFS=<dataset>
* Remove the existing '-f' option to 'zpool import', instead let
  this be controlled on the kernel command line.
* Do not force-set mountpoint=/ - should (??) not be nessesary.
* Support mounting a rootfs with mountpoint=legacy
* Support both RPM based and DEB based system by removing the logic
  from the dracut script and instead use the logic in scripts/zfs-initramfs/scripts/zfs
  for both Debian GNU/Linux (etc) and RedHat/Fedora (etc).
* Only run the local-* script(s) if/when it/they exists.
* Don't auto import pools when loading module - keep better control of the imports.
* If called with only 'rpool' (or only 'zfs-bootfs'), then fake it by setting 'root=zfs:AUTO'
  (to avoid duplication of code etc) so that it will be auto detected later.
  + If pool is specified and we're auto discovering, don't go through ALL pools, only the one we specified.
* Rewrite the auto detection of bootfs in the auto detector.
* Only try to import pool if it haven't already been imported (in the auto detector).
* Add support for only having 'root=pool/dataset' option.
* Remove the use of setting 'ZFS_RPOOL=rpool'. No longer nessesary.
* Check if /scripts/local-* is either file or directory - should be dir, but just to be safe check both.
* Make wait_for_udev wait for 10 seconds.
* Add a configurable ZFS_INITRD_POST_MODPROBE_SLEEP (set in /etc/default/zfs) after the modprobe.
* Merge openzfs#2196.
  Remove lines that contain only a hyphen (match '^-$' instead of '-').
  • Loading branch information
FransUrbo committed Mar 21, 2014
1 parent 98fad86 commit 0455bcb
Show file tree
Hide file tree
Showing 6 changed files with 610 additions and 66 deletions.
6 changes: 4 additions & 2 deletions dracut/90zfs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ pkgdracutdir = $(dracutdir)/modules.d/90zfs
pkgdracut_SCRIPTS = \
$(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)/scripts/zfs-initramfs/scripts/zfs

EXTRA_DIST = \
$(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)/scripts/zfs-initramfs/scripts/zfs

$(pkgdracut_SCRIPTS):
-$(SED) -e 's,@bindir\@,$(bindir),g' \
Expand Down
1 change: 1 addition & 0 deletions dracut/90zfs/module-setup.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ install() {
dracut_install @udevdir@/zvol_id
dracut_install mount.zfs
dracut_install hostid
dracut_install /usr/lib/dracut/modules.d/90zfs/zfs
inst_hook cmdline 95 "$moddir/parse-zfs.sh"
inst_hook mount 98 "$moddir/mount-zfs.sh"

Expand Down
88 changes: 24 additions & 64 deletions dracut/90zfs/mount-zfs.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,30 @@

. /lib/dracut-lib.sh

ZPOOL_FORCE=""

if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then
warn "ZFS: Will force-import pools if necessary."
ZPOOL_FORCE="-f"
# Of course the functions we need is called differently
# on different distributions - it would be way to easy
# otherwise!!
if type log_failure_msg > /dev/null 2>&1 ; then
# LSB functions
log_begin_msg=log_begin_msg
log_failure_msg=log_failure_msg
log_progress_msg=log_progress_msg
elif type success > /dev/null 2>&1 ; then
# Fedora/RedHat functions
log_begin_msg=success
log_failure_msg=failure
log_progress_msg="echo -n"
elif type einfo > /dev/null 2>&1 ; then
# Gentoo functions
log_begin_msg=einfo
log_failure_msg=eerror
log_progress_msg="echo -n"
else
log_begin_msg="echo -n"
log_failure_msg=echo
log_progress_msg="echo -n"
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 -n '/-/ !p' | sed 'q'`
if [ "$?" != "0" ] || [ "$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 [ "$?" != "0" ] || [ "$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.
zpool list -H | while read fs rest ; do
zpool export "$fs"
done

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
. /usr/lib/dracut/modules.d/90zfs/zfs

# 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
mountroot
2 changes: 2 additions & 0 deletions scripts/zfs-initramfs/conf-hooks.d/zfs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Force the inclusion of Busybox in the initramfs.
BUSYBOX=y
100 changes: 100 additions & 0 deletions scripts/zfs-initramfs/hooks/zfs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/sh
#
# Add ZoL filesystem capabilities to an initrd, usually for a native ZFS root.
#

# This hook installs udev rules for ZoL.
PREREQ="zdev"

# These prerequisites are provided by the zfsutils package. The zdb utility is
# not strictly required, but it can be useful at the initramfs recovery prompt.
COPY_EXEC_LIST="/sbin/zdb /sbin/zpool /sbin/zfs /sbin/mount.zfs"

# These prerequisites are provided by the base system.
COPY_EXEC_LIST="$COPY_EXEC_LIST /bin/hostname /sbin/blkid"

# Explicitly specify all kernel modules because automatic dependency resolution
# is unreliable on many systems.
BASE_MODULES="zlib_deflate spl zavl zcommon znvpair zunicode zfs"
CRPT_MODULES="sun-ccm sun-gcm sun-ctr"
MANUAL_ADD_MODULES_LIST="$BASE_MODULES"

# Generic result code.
RC=0

case $1 in
prereqs)
echo "$PREREQ"
exit 0
;;
esac

for ii in $COPY_EXEC_LIST
do
if [ ! -x "$ii" ]
then
echo "Error: $ii is not executable."
RC=2
fi
done

if [ "$RC" -ne 0 ]
then
exit "$RC"
fi

. /usr/share/initramfs-tools/hook-functions

mkdir -p "$DESTDIR/etc/"

# ZDB uses pthreads for some functions, but the library dependency is not
# automatically detected. The `find` utility and extended `cp` options are
# used here because libgcc_s.so could be in a subdirectory of /lib for
# multi-arch installations.
cp --target-directory="$DESTDIR" --parents $(find /lib -type f -name libgcc_s.so.1)

for ii in $COPY_EXEC_LIST
do
copy_exec "$ii"
done

for ii in $MANUAL_ADD_MODULES_LIST
do
manual_add_modules "$ii"
done

if [ -f "/etc/hostname" ]
then
cp -p "/etc/hostname" "$DESTDIR/etc/"
else
hostname >"$DESTDIR/etc/hostname"
fi

for ii in zfs spl
do
if [ -f "/etc/modprobe.d/$ii" ]; then
if [ ! -d "$DESTDIR//etc/modprobe.d" ]; then
mkdir -p $DESTDIR//etc/modprobe.d
fi
cp -p "/etc/modprobe.d/$ii" $DESTDIR//etc/modprobe.d/
fi
done

# The spl-dkms package ensures that the /etc/hostid file exists.
# NB: Commentary in the spl-dkms.postinst script.
[ -f "/etc/hostid" ] && cp -p "/etc/hostid" "$DESTDIR/etc/hostid"

# Install the zpool.cache file.
[ ! -d "$DESTDIR/boot/zfs" ] && mkdir -p "$DESTDIR/boot/zfs"
[ -d /boot/zfs ] && cp -r /boot/zfs "$DESTDIR/boot"

# With pull request #1476 (not yet merged) comes a verbose warning
# if /usr/bin/net doesn't exist or isn't executable. Just create
# a dummy...
[ ! -d "$DESTDIR/usr/bin" ] && mkdir -p "$DESTDIR/usr/bin"
if [ ! -x "$DESTDIR/usr/bin/net" ]; then
touch "$DESTDIR/usr/bin/net"
chmod +x "$DESTDIR/usr/bin/net"
fi

exit 0
Loading

0 comments on commit 0455bcb

Please sign in to comment.