Skip to content

Commit

Permalink
Fixing some issues disovered.
Browse files Browse the repository at this point in the history
  * Use "${VAR}" instead of "$VAR".
  * Create zfs_run_cmd() which records stderr, exit code etc.
  * Create check_boolean() to check if a user config option is
    set ('yes', 'Yes', 'YES' or any combination there of) OR '1'.
    Anything else is considered 'unset'.
  * Put the check for zfs debugging in check_zfs_debug(). Use this in
    zfs_action() to check if we should output the message we're called
    with.
  * Move code snippet that fetches and mounts recursive filesystems into
    the new recursive_mount_filesystems() function.
  * Minor fix/change to read_mtab():
    * Strip control characters (space - \040) from /proc/mounts GLOBALY,
      not just first occurrence.
    * Don't replace unprintable characters ([/-. ]) for use in the variable
      name with underscore. No need, just remove them all together.
  * Instead of using ZFS_CMD+zfs_action()+zfs_log_failure_msg() etc
    each and every time, use the more generic zfs_action() that does
    most of this for us.
    * Downside: Won't accept pools with spaces in them any more :(.
      Need to find a way to solve this (can't use arrays, because we're
      not running under bash!).
  * Apparently "var > 0" doesn't work. Use 'var -gt 0' instead. But that
    means that 'var' needs to be set.
  * (Re)set IFS in zfs_action() as first step so that command line options
    doesn't get clobbered.
  * Fix checking if pool is imported in import_pool().
  * Remove "sort". Sometimes not available, and not really nessesary.
  * Add ZPOOL_CACHE option (commented out) and documentation in the defaults
    file to indicate that the default in zfs-functions can be overwritten.
    * Needed when/if enforcing the use of a cache file is needed/wanted.
  * Remove some 'local' variables in do_import().

Signed-off-by: Turbo Fredriksson <[email protected]>
Closes openzfs#3782
Closes openzfs#3777
Closes zfsonlinux/pkg-zfs#166
  • Loading branch information
FransUrbo committed Sep 19, 2015
1 parent 496a20d commit f526b46
Show file tree
Hide file tree
Showing 6 changed files with 427 additions and 384 deletions.
127 changes: 65 additions & 62 deletions contrib/initramfs/scripts/zfs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,30 @@ ZPOOL="/sbin/zpool"
ZPOOL_CACHE="/etc/zfs/zpool.cache"
export ZFS ZPOOL ZPOOL_CACHE

# Needs to be set for rest of the code to work.
[ -z "${ZFS_INITRD_PRE_MOUNTROOT_SLEEP}" ] && ZFS_INITRD_PRE_MOUNTROOT_SLEEP=0
[ -z "${ZFS_INITRD_POST_MODPROBE_SLEEP}" ] && ZFS_INITRD_POST_MODPROBE_SLEEP=0

# This runs any scripts that should run before we start importing
# pools and mounting any filesystems.
pre_mountroot()
{
if type run_scripts > /dev/null 2>&1 && \
[ -f "/scripts/local-top" -o -d "/scripts/local-top" ]
then
[ "$quiet" != "y" ] && \
[ "${quiet}" != "y" ] && \
zfs_log_begin_msg "Running /scripts/local-top"
run_scripts /scripts/local-top
[ "$quiet" != "y" ] && zfs_log_end_msg
[ "${quiet}" != "y" ] && zfs_log_end_msg
fi

if type run_scripts > /dev/null 2>&1 && \
[ -f "/scripts/local-premount" -o -d "/scripts/local-premount" ]
then
[ "$quiet" != "y" ] && \
[ "${quiet}" != "y" ] && \
zfs_log_begin_msg "Running /scripts/local-premount"
run_scripts /scripts/local-premount
[ "$quiet" != "y" ] && zfs_log_end_msg
[ "${quiet}" != "y" ] && zfs_log_end_msg
fi
}

Expand All @@ -53,14 +57,14 @@ disable_plymouth()
# with more logging etc.
load_module_initrd()
{
if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" > 0 ]
if [ "${ZFS_INITRD_PRE_MOUNTROOT_SLEEP}" -gt 0 ]
then
if [ "$quiet" != "y" ]; then
if [ "${quiet}" != "y" ]; then
zfs_log_begin_msg "Sleeping for" \
"$ZFS_INITRD_PRE_MOUNTROOT_SLEEP seconds..."
"${ZFS_INITRD_PRE_MOUNTROOT_SLEEP} seconds..."
fi
sleep "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP"
[ "$quiet" != "y" ] && zfs_log_end_msg
sleep "${ZFS_INITRD_PRE_MOUNTROOT_SLEEP}"
[ "${quiet}" != "y" ] && zfs_log_end_msg
fi

# Wait for all of the /dev/{hd,sd}[a-z] device nodes to appear.
Expand All @@ -77,14 +81,14 @@ load_module_initrd()
# Load the module
load_module "zfs" || return 1

if [ "$ZFS_INITRD_POST_MODPROBE_SLEEP" > 0 ]
if [ "${ZFS_INITRD_POST_MODPROBE_SLEEP}" -gt 0 ]
then
if [ "$quiet" != "y" ]; then
if [ "${quiet}" != "y" ]; then
zfs_log_begin_msg "Sleeping for" \
"$ZFS_INITRD_POST_MODPROBE_SLEEP seconds..."
"${ZFS_INITRD_POST_MODPROBE_SLEEP} seconds..."
fi
sleep "$ZFS_INITRD_POST_MODPROBE_SLEEP"
[ "$quiet" != "y" ] && zfs_log_end_msg
sleep "${ZFS_INITRD_POST_MODPROBE_SLEEP}"
[ "${quiet}" != "y" ] && zfs_log_end_msg
fi

return 0
Expand All @@ -95,9 +99,7 @@ load_module_initrd()
# This is the main function.
mountroot()
{
local snaporig
local snapsub
local destfs
local snaporig snapsub destfs pool POOLS

# ----------------------------------------------------------------
# I N I T I A L S E T U P
Expand All @@ -112,7 +114,7 @@ mountroot()

# ------------
# Support debug option
if grep -qiE '(^|[^\\](\\\\)* )(zfs_debug|zfs\.debug|zfsdebug)=(on|yes|1)( |$)' /proc/cmdline
if check_zfs_debug
then
ZFS_DEBUG=1
mkdir /var/log
Expand All @@ -138,30 +140,30 @@ mountroot()
# Compatibility: 'ROOT' is for Debian GNU/Linux (etc),
# 'root' is for Redhat/Fedora (etc),
# 'REAL_ROOT' is for Gentoo
if [ -z "$ROOT" ]
if [ -z "${ROOT}" ]
then
[ -n "$root" ] && ROOT=${root}
[ -n "${root}" ] && ROOT=${root}

[ -n "$REAL_ROOT" ] && ROOT=${REAL_ROOT}
[ -n "${REAL_ROOT}" ] && ROOT=${REAL_ROOT}
fi

# ------------
# Where to mount the root fs in the initrd - set outside this script
# Compatibility: 'rootmnt' is for Debian GNU/Linux (etc),
# 'NEWROOT' is for RedHat/Fedora (etc),
# 'NEW_ROOT' is for Gentoo
if [ -z "$rootmnt" ]
if [ -z "${rootmnt}" ]
then
[ -n "$NEWROOT" ] && rootmnt=${NEWROOT}
[ -n "${NEWROOT}" ] && rootmnt=${NEWROOT}

[ -n "$NEW_ROOT" ] && rootmnt=${NEW_ROOT}
[ -n "${NEW_ROOT}" ] && rootmnt=${NEW_ROOT}
fi

# ------------
# No longer set in the defaults file, but it could have been set in
# get_pools() in some circumstances. If it's something, but not 'yes',
# it's no good to us.
[ -n "$USE_DISK_BY_ID" -a "$USE_DISK_BY_ID" != 'yes' ] && \
[ -n "${USE_DISK_BY_ID}" -a "${USE_DISK_BY_ID}" != 'yes' ] && \
unset USE_DISK_BY_ID

# ----------------------------------------------------------------
Expand Down Expand Up @@ -200,19 +202,19 @@ mountroot()

# ------------
# Look for 'rpool' and 'bootfs' parameter
[ -n "$rpool" ] && ZFS_RPOOL="${rpool#rpool=}"
[ -n "$bootfs" ] && ZFS_BOOTFS="${bootfs#bootfs=}"
[ -n "${rpool}" ] && ZFS_RPOOL="${rpool#rpool=}"
[ -n "${bootfs}" ] && ZFS_BOOTFS="${bootfs#bootfs=}"

# ------------
# If we have 'ROOT' (see above), but not 'ZFS_BOOTFS', then use
# 'ROOT'
[ -n "$ROOT" -a -z "${ZFS_BOOTFS}" ] && ZFS_BOOTFS="$ROOT"
[ -n "${ROOT}" -a -z "${ZFS_BOOTFS}" ] && ZFS_BOOTFS="${ROOT}"

# ------------
# Check for the `-B zfs-bootfs=%s/%u,...` kind of parameter.
# NOTE: Only use the pool name and dataset. The rest is not
# supported by ZoL (whatever it's for).
if [ -z "$ZFS_RPOOL" ]
if [ -z "${ZFS_RPOOL}" ]
then
# The ${zfs-bootfs} variable is set at the kernel commmand
# line, usually by GRUB, but it cannot be referenced here
Expand All @@ -227,7 +229,7 @@ mountroot()

# ------------
# No root fs or pool specified - do auto detect.
if [ -z "$ZFS_RPOOL" -a -z "${ZFS_BOOTFS}" ]
if [ -z "${ZFS_RPOOL}" -a -z "${ZFS_BOOTFS}" ]
then
# Do auto detect. Do this by 'cheating' - set 'root=zfs:AUTO'
# which will be caught later
Expand All @@ -238,33 +240,33 @@ mountroot()
# F I N D A N D I M P O R T C O R R E C T P O O L

# ------------
if [ "$ROOT" = "zfs:AUTO" ]
if [ "${ROOT}" = "zfs:AUTO" ]
then
# Try to detect both pool and root fs.

[ "$quiet" != "y" ] && \
[ "${quiet}" != "y" ] && \
zfs_log_begin_msg "Attempting to import additional pools."

# Get a list of pools available for import
if [ -n "$ZFS_RPOOL" ]
if [ -n "${ZFS_RPOOL}" ]
then
# We've specified a pool - check only that
POOLS=$ZFS_RPOOL
POOLS=${ZFS_RPOOL}
else
POOLS=$(get_pools)
fi

OLD_IFS="$IFS" ; IFS=";"
for pool in $POOLS
for pool in ${POOLS}
do
[ -z "$pool" ] && continue
[ -z "${pool}" ] && continue

import_pool "$pool"
find_rootfs "$pool"
import_pool "${pool}"
find_rootfs "${pool}"
done
IFS="$OLD_IFS"

[ "$quiet" != "y" ] && zfs_log_end_msg $ZFS_ERROR
[ "${quiet}" != "y" ] && zfs_log_end_msg $ZFS_ERROR
else
# No auto - use value from the command line option.

Expand All @@ -276,15 +278,10 @@ mountroot()
fi

# Import the pool (if not already done so in the AUTO check above).
if [ -n "$ZFS_RPOOL" -a -z "${POOL_IMPORTED}" ]
if [ -n "${ZFS_RPOOL}" -a -z "${POOL_IMPORTED}" ]
then
[ "$quiet" != "y" ] && \
zfs_log_begin_msg "Importing ZFS root pool '$ZFS_RPOOL'"

import_pool "${ZFS_RPOOL}"
find_rootfs "${ZFS_RPOOL}"

[ "$quiet" != "y" ] && zfs_log_end_msg
fi

if [ -z "${POOL_IMPORTED}" ]
Expand Down Expand Up @@ -322,8 +319,8 @@ mountroot()
echo "Error: Unknown root filesystem - no 'bootfs' pool property and"
echo " not specified on the kernel command line."
echo ""
echo "Manually mount the root filesystem on $rootmnt and then exit."
echo "Hint: Try: mount -o zfsutil -t zfs ${ZFS_RPOOL-rpool}/ROOT/system $rootmnt"
echo "Manually mount the root filesystem on ${rootmnt} and then exit."
echo "Hint: Try: mount -o zfsutil -t zfs ${ZFS_RPOOL-rpool}/ROOT/system ${rootmnt}"
emergency_shell
fi

Expand All @@ -332,7 +329,7 @@ mountroot()

# * Ideally, the root filesystem would be mounted like this:
#
# zpool import -R "$rootmnt" -N "$ZFS_RPOOL"
# zpool import -R "${rootmnt}" -N "${ZFS_RPOOL}"
# zfs mount -o mountpoint=/ "${ZFS_BOOTFS}"
#
# but the MOUNTPOINT prefix is preserved on descendent filesystem
Expand All @@ -343,20 +340,28 @@ mountroot()
# Such as /usr, /var, /usr/local etc.
# NOTE: Mounted in the order specified in the
# ZFS_INITRD_ADDITIONAL_DATASETS variable so take care!

# Go through the complete list (recursivly) of all filesystems below
# the real root dataset
filesystems=$("${ZFS}" list -oname -tfilesystem -H -r "${ZFS_BOOTFS}")
for fs in $filesystems $ZFS_INITRD_ADDITIONAL_DATASETS
do
mount_fs "$fs"
done
recursive_mount_filesystems "Using ${ZFS_BOOTFS} as root." "${ZFS_BOOTFS}"
if [ "${ZFS_ERROR}" != 0 ]
then
disable_plymouth
echo ""
echo "Command: ${ZFS_CMD}"
echo "Message: ${ZFS_STDERR}"
echo "Error: ${ZFS_ERROR}"
echo ""
echo "Error: Failed to mount root filesystem '${ZFS_BOOTFS}'."
echo ""
echo "Manually mount the filesystem and exit."
echo "Hint: Try: mount -o zfsutil -t zfs ${ZFS_BOOTFS} ${rootmnt}"
emergency_shell
fi

# ------------
# Debugging information
if [ -n "${ZFS_DEBUG}" ]
then
#exec 2>&1-
set +x

echo "DEBUG: imported pools:"
"${ZPOOL}" list -H
Expand All @@ -370,20 +375,18 @@ mountroot()
echo -n " 'c' for shell, 'r' for reboot, 'ENTER' to continue. "
read b

[ "$b" = "c" ] && emergency_shell
[ "$b" = "r" ] && reboot -f

set +x
[ "${b}" = "c" ] && emergency_shell
[ "${b}" = "r" ] && reboot -f
fi

# ------------
# Run local bottom script
if type run_scripts > /dev/null 2>&1 && \
[ -f "/scripts/local-bottom" -o -d "/scripts/local-bottom" ]
then
[ "$quiet" != "y" ] && \
[ "${quiet}" != "y" ] && \
zfs_log_begin_msg "Running /scripts/local-bottom"
run_scripts /scripts/local-bottom
[ "$quiet" != "y" ] && zfs_log_end_msg
[ "${quiet}" != "y" ] && zfs_log_end_msg
fi
}
Loading

0 comments on commit f526b46

Please sign in to comment.