Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
zfs-initramfs: Re-architect scripts/zfs
This has the following changes:
1) ZFS_INITRD_PRE_MOUNTROOT_SLEEP is replaced by honoring the standard
   parameter "rootdelay" in the following way:  the pool is repeatedly
   imported read-only until it has a health status of ONLINE or
   rootdelay expires.  In this way, the script will wait for missing
   drives until rootdelay expires.  But in all cases, it tries a
   read-write import of the pool eventually.

   Using a standard parameter is more consistent than a ZFS-specific
   option.  Also, this establishes a maximum delay (well, not counting
   the `zpool import` and `zpool export` time) rather than a minimum
   delay, so if the drives are available sooner, the boot is faster.
   This also allows one to set the option with a reasonable margin of
   safety (so if one day the drives are just a little slower, the
   system still boots) without unnecessarily delaying boots.

   The condition of the pool needing to be ONLINE could probably be
   tightened to looking at `zpool status` for some combination of
   conditions (probably UNAVAIL, MISSING, FAULTED), but this is a safe
   starting point.  The only downside of this approach is that
   offlining a drive and rebooting will require enduring the full
   rootdelay unnecessarily.  But given that rootdelay defaults to zero,
   some portion of that is expected, and the maximum is still a value
   the administrator has explicitly chosen as something they accept.

2) Direct error echos and /bin/sh calls are replaced by the standard
   panic function.  This achieves a nearly identical result, but:
   A) is consistent with the standard behavior, including...
   B) honors the standard "panic=" option to disable the debug shell
      for security reasons.  I'm not sure how important this is, but
      it is standard behavior.
   C) it requires less code; it eliminates the code to disable plymouth
      directly.

3) Automatic pool imports are disabled.  This is the default in 0.6.4
   anyway.

4) Forced pool importing is eliminated.  This should not be necessary.

5) Only the upstream root=ZFS= syntax is supported for specifying the
   root pool and bootfs.

6) All environment variables that are set are unset to avoid polluting
   the init environment.  This is an explicit goal of the upstream
   scripts.  Again, I'm not sure how important it is.
  • Loading branch information
rlaager committed Feb 22, 2015
1 parent d3cab97 commit 50f3051
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 117 deletions.
163 changes: 50 additions & 113 deletions debian/tree/zfs-initramfs/usr/share/initramfs-tools/scripts/zfs
@@ -1,43 +1,21 @@
# ZFS boot stub for initramfs-tools.
#
# In the initramfs environment, the /init script sources this stub to
# override the default functions in the /scripts/local script.
#
# Enable this by passing boot=zfs on the kernel command line.
#


pre_mountroot()
{
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-top"
run_scripts /scripts/local-top
[ "$quiet" != "y" ] && log_end_msg

if [ -r '/etc/default/zfs' ]
then
. '/etc/default/zfs'
if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" -gt '0' ]
then
[ "$quiet" != "y" ] && log_begin_msg "Sleeping for $ZFS_INITRD_PRE_MOUNTROOT_SLEEP seconds..."
sleep "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP"
[ "$quiet" != "y" ] && log_end_msg
fi
fi
}

# Duplicates the functionality found under try_failure_hooks in functions
# but invoking that would be inappropriate here.
disable_plymouth()
zfs_test_import()
{
if [ -x /bin/plymouth ] && /bin/plymouth --ping
ZFS_STDERR=$(zpool import -o readonly=on -N "$ZFS_RPOOL" 2>&1)
ZFS_ERROR=$?
if [ "$ZFS_ERROR" -eq 0 ]
then
/bin/plymouth hide-splash >/dev/null 2>&1
ZFS_HEALTH=$(zpool list -H -o health "$ZFS_RPOOL" 2>/dev/null)
fi
zpool export "$ZFS_RPOOL" >/dev/null 2>&1
}

mountroot()
{
pre_mountroot
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-top"
run_scripts /scripts/local-top
[ "$quiet" != "y" ] && log_end_msg

[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-premount"
run_scripts /scripts/local-premount
Expand All @@ -46,90 +24,47 @@ mountroot()
# Wait for all of the /dev/{hd,sd}[a-z] device nodes to appear.
wait_for_udev

# Load the module now to get consistent automatic pool import behavior.
modprobe zfs
modprobe zfs zfs_autoimport_disable=1

# Check the kernel command line for overrides.
ZFS_RPOOL="${rpool#rpool=}"
ZFS_BOOTFS="${bootfs#bootfs=}"
ZFS_BOOTFS=${ROOT#ZFS=}
ZFS_RPOOL=$(echo "$ZFS_BOOTFS" | sed -e 's,/.*,,')

if [ -z "$ZFS_RPOOL" ]
then
# Check for the `-B zfs-bootfs=%s/%u,...` kind of parameter.
#
# The ${zfs-bootfs} variable is set at the kernel commmand
# line, usually by GRUB, but it cannot be referenced here
# directly because bourne variable names cannot contain a
# hyphen.
#
# Reassign the variable by dumping the environment and
# stripping the zfs-bootfs= prefix. Let the shell handle
# quoting through the eval command.
eval ZFS_RPOOL=$(set | sed -n -e 's,^zfs-bootfs=,,p')

# Only the pool name is relevant because the ZFS filesystem on
# Linux is extrinsic and the userland cannot resolve a ZFS
# object number.
#
# Strip everything after the first slash character.
ZFS_RPOOL=$(echo "$ZFS_RPOOL" | sed -e 's,/.*,,')
fi
delay=${ROOTDELAY:-0}

if [ -z "$ZFS_RPOOL" ]
if [ "$delay" -gt 0 ]
then
ZFS_BOOTFS=${ROOT#ZFS=}
ZFS_RPOOL=$(echo "$ZFS_BOOTFS" | sed -e 's,/.*,,')
# Try to import the pool read-only. If it does not import with
# the ONLINE status, wait and try again. The pool could be
# DEGRADED because a drive is really missing, or it might just
# be slow to be detected.
zfs_test_import
retry_nr=0
while [ "$retry_nr" -lt "$delay" ] && [ "$ZFS_HEALTH" != "ONLINE" ]
do
[ "$quiet" != "y" ] && log_begin_msg "Retrying ZFS read-only import"
/bin/sleep 1
zfs_test_import
retry_nr=$(( $retry_nr + 1 ))
[ "$quiet" != "y" ] && log_end_msg
done
unset retry_nr
unset ZFS_HEALTH
fi
unset delay

# Use "rpool" as the default, like on most Solaris systems.
[ -z "$ZFS_RPOOL" ] && ZFS_RPOOL='rpool'

# @FIXME: Forcing the import should not be necessary.
#
# Consider inhibiting automatic zpool imports in the initramfs
# environment and doing a full import in the regular system instead.

[ "$quiet" != "y" ] && log_begin_msg "Importing ZFS root pool $ZFS_RPOOL"
if [ -f /etc/zfs/zpool.cache ]
then
ZFS_STDERR=$(zpool list "$ZFS_RPOOL" 1>/dev/null 2>&1 \
|| zpool import -f -N "$ZFS_RPOOL" 2>&1)
ZFS_ERROR=$?
else
ZFS_STDERR=$(zpool import -f -N "$ZFS_RPOOL" 2>&1)
ZFS_ERROR=$?
fi
[ "$quiet" != "y" ] && log_end_msg
# At this point, the pool either imported cleanly, or we ran out of the
# allowed time (rootdelay). Perform the read-write import.
ZFS_STDERR=$(zpool import -N "$ZFS_RPOOL" 2>&1)
ZFS_ERROR=$?

if [ "$ZFS_ERROR" -ne 0 ]
then
disable_plymouth
echo "Command: zpool import -f -N $ZFS_RPOOL"
echo "Message: $ZFS_STDERR"
echo "Error: $ZFS_ERROR"
echo ""
echo "Manually import the root pool at the command prompt and then exit."
echo "Hint: Try: zpool import -f -R / -N $ZFS_RPOOL"
/bin/sh
fi

if [ -z "$ZFS_BOOTFS" ]
then
[ "$quiet" != "y" ] && log_begin_msg "Getting ZFS bootfs property"
ZFS_BOOTFS=$(zpool list -H -o bootfs "$ZFS_RPOOL")
ZFS_ERROR=$?
[ "$quiet" != "y" ] && log_end_msg
fi
panic "Command: zpool import -N $ZFS_RPOOL
Message: $ZFS_STDERR
Error: $ZFS_ERROR

if [ -z "$ZFS_BOOTFS" ]
then
disable_plymouth
echo "Command: zpool list -H -o bootfs $ZFS_RPOOL"
echo "Error: $ZFS_ERROR, unable to get the bootfs property."
echo ""
echo "Manually mount the root filesystem on $rootmnt and then exit."
echo "Hint: Try: mount -t zfs -o zfsutil $ZFS_RPOOL/ROOT/system $rootmnt"
/bin/sh
Manually import the root pool at the command prompt and then exit.
Hint: Try: zpool import -f -R / -N $ZFS_RPOOL"
fi

# Force the mountpoint to the only correct value for a root filesystem.
Expand All @@ -153,16 +88,18 @@ mountroot()

if [ "$ZFS_ERROR" -ne 0 ]
then
disable_plymouth
echo ""
echo "Command: mount -t zfs -o zfsutil $ZFS_BOOTFS $rootmnt"
echo "Message: $ZFS_STDERR"
echo "Error: $ZFS_ERROR"
echo ""
echo "Manually mount the root filesystem on $rootmnt and then exit."
/bin/sh
panic "Command: mount -t zfs -o zfsutil $ZFS_BOOTFS $rootmnt
Message: $ZFS_STDERR
Error: $ZFS_ERROR

Manually mount the root filesystem on $rootmnt and then exit."
fi

unset ZFS_BOOTFS
unset ZFS_RPOOL
unset ZFS_STDERR
unset ZFS_ERROR

[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
run_scripts /scripts/local-bottom
[ "$quiet" != "y" ] && log_end_msg
Expand Down
4 changes: 0 additions & 4 deletions debian/zfsutils.zfs.default
Expand Up @@ -19,7 +19,3 @@ ZFS_DKMS_ENABLE_DEBUG_DMU_TX='no'

# Keep debugging symbols in kernel modules?
ZFS_DKMS_DISABLE_STRIP='no'

# Wait for this many seconds in the initrd pre_mountroot?
# This delays startup and should be '0' on most systems.
ZFS_INITRD_PRE_MOUNTROOT_SLEEP='0'
25 changes: 25 additions & 0 deletions debian/zfsutils.zfs.default.orig
@@ -0,0 +1,25 @@
# ZoL userland configuration.

# Wait this many seconds during system start for pool member devices to appear
# before attempting import and starting mountall.
ZFS_AUTOIMPORT_TIMEOUT='30'

# Run `zfs share -a` during system start?
# nb: The shareiscsi, sharenfs, and sharesmb dataset properties.
ZFS_SHARE='no'

# Run `zfs unshare -a` during system stop?
ZFS_UNSHARE='no'

# Build kernel modules with the --enable-debug switch?
ZFS_DKMS_ENABLE_DEBUG='no'

# Build kernel modules with the --enable-debug-dmu-tx switch?
ZFS_DKMS_ENABLE_DEBUG_DMU_TX='no'

# Keep debugging symbols in kernel modules?
ZFS_DKMS_DISABLE_STRIP='no'

# Wait for this many seconds in the initrd pre_mountroot?
# This delays startup and should be '0' on most systems.
ZFS_INITRD_PRE_MOUNTROOT_SLEEP='0'

0 comments on commit 50f3051

Please sign in to comment.