zfs/etc/init.d/zfs-import.in

356 lines
8.5 KiB
Plaintext
Executable File

#!@SHELL@
#
# zfs-import This script will import/export zfs pools.
#
# chkconfig: 2345 01 99
# description: This script will import/export zfs pools during system
# boot/shutdown.
# It is also responsible for all userspace zfs services.
# probe: true
#
### BEGIN INIT INFO
# Provides: zfs-import
# Required-Start: zfs-zed
# Required-Stop: zfs-zed
# Default-Start: S
# Default-Stop: 0 1 6
# X-Start-Before: checkfs
# X-Stop-After: zfs-mount
# Short-Description: Import ZFS pools
# Description: Run the `zpool import` or `zpool export` commands.
### END INIT INFO
#
# Released under the 2-clause BSD license.
#
# The original script that acted as a template for this script came from
# the Debian GNU/Linux kFreeBSD ZFS packages (which did not include a
# licensing stansa) in the commit dated Mar 24, 2011:
# https://github.com/zfsonlinux/pkg-zfs/commit/80a3ae582b59c0250d7912ba794dca9e669e605a
# Source the common init script
. @sysconfdir@/zfs/zfs-functions
# ----------------------------------------------------
do_depend()
{
after sysfs udev zfs-zed
keyword -lxc -openvz -prefix -vserver
}
# Support function to get a list of all pools, separated with ';'
find_pools()
{
local CMD="$*"
local pools
pools=$($CMD 2> /dev/null | \
grep -E "pool:|^[a-zA-Z0-9]" | \
sed 's@.*: @@' | \
sort | \
while read pool; do \
echo -n "$pool;"
done)
echo "${pools%%;}" # Return without the last ';'.
}
# Import all pools
do_import()
{
local already_imported available_pools pool npools
local exception dir ZPOOL_IMPORT_PATH RET=0 r=1
# In case not shutdown cleanly.
[ -n "$init" ] && rm -f /etc/dfs/sharetab
# Just simplify code later on.
if [ -n "$USE_DISK_BY_ID" -a "$USE_DISK_BY_ID" != 'yes' ]
then
# It's something, but not 'yes' so it's no good to us.
unset USE_DISK_BY_ID
fi
# Find list of already imported pools.
already_imported=$(find_pools "$ZPOOL" list -H -oname)
available_pools=$(find_pools "$ZPOOL" import)
# Just in case - seen it happen (that a pool isn't visable/found
# with a simple "zpool import" but only when using the "-d"
# option or setting ZPOOL_IMPORT_PATH).
if [ -d "/dev/disk/by-id" ]
then
npools=$(find_pools "$ZPOOL" import -d /dev/disk/by-id)
if [ -n "$npools" ]
then
# Because we have found extra pool(s) here, which wasn't
# found 'normaly', we need to force USE_DISK_BY_ID to
# make sure we're able to actually import it/them later.
USE_DISK_BY_ID='yes'
if [ -n "$available_pools" ]
then
# Filter out duplicates (pools found with the simpl
# "zpool import" but which is also found with the
# "zpool import -d ...").
npools=$(echo "$npools" | sed "s,$available_pools,,")
# Add the list to the existing list of
# available pools
available_pools="$available_pools;$npools"
else
available_pools="$npools"
fi
fi
fi
# Filter out any exceptions...
if [ -n "$ZFS_POOL_EXCEPTIONS" ]
then
local found=""
local apools=""
OLD_IFS="$IFS" ; IFS=";"
for pool in $available_pools
do
for exception in $ZFS_POOL_EXCEPTIONS
do
[ "$pool" = "$exception" ] && continue 2
found="$pool"
done
if [ -n "$found" ]
then
if [ -n "$apools" ]
then
apools="$apools;$pool"
else
apools="$pool"
fi
fi
done
IFS="$OLD_IFS"
available_pools="$apools"
fi
# For backwards compability, make sure that ZPOOL_IMPORT_PATH is set
# to something we can use later with the real import(s). We want to
# make sure we find all by* dirs, BUT by-vdev should be first (if it
# exists).
if [ -n "$USE_DISK_BY_ID" -a -z "$ZPOOL_IMPORT_PATH" ]
then
local dirs
dirs="$(for dir in $(echo /dev/disk/by-*)
do
# Ignore by-vdev here - we wan't it first!
echo "$dir" | grep -q /by-vdev && continue
[ ! -d "$dir" ] && continue
echo -n "$dir:"
done | sed 's,:$,,g')"
if [ -d "/dev/disk/by-vdev" ]
then
# Add by-vdev at the beginning.
ZPOOL_IMPORT_PATH="/dev/disk/by-vdev:"
fi
# Help with getting LUKS partitions etc imported.
if [ -d "/dev/mapper" ]; then
if [ -n "$ZPOOL_IMPORT_PATH" ]; then
ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH:/dev/mapper:"
else
ZPOOL_IMPORT_PATH="/dev/mapper:"
fi
fi
# ... and /dev at the very end, just for good measure.
ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH$dirs:/dev"
fi
# Needs to be exported for "zpool" to catch it.
[ -n "$ZPOOL_IMPORT_PATH" ] && export ZPOOL_IMPORT_PATH
# Mount all availible pools (except those set in ZFS_POOL_EXCEPTIONS.
#
# If not interactive (run from init - variable init='/sbin/init')
# we get ONE line for all pools being imported, with just a dot
# as status for each pool.
# Example: Importing ZFS pool(s)... [OK]
#
# If it IS interactive (started from the shell manually), then we
# get one line per pool importing.
# Example: Importing ZFS pool pool1 [OK]
# Importing ZFS pool pool2 [OK]
# [etc]
[ -n "$init" ] && zfs_log_begin_msg "Importing ZFS pool(s)"
OLD_IFS="$IFS" ; IFS=";"
for pool in $available_pools
do
[ -z "$pool" ] && continue
# We have pools that haven't been imported - import them
if [ -n "$init" ]
then
# Not interactive - a dot for each pool.
# Except on Gentoo where this doesn't work.
zfs_log_progress_msg "."
else
# Interactive - one 'Importing ...' line per pool
zfs_log_begin_msg "Importing ZFS pool $pool"
fi
# Import by using ZPOOL_IMPORT_PATH (either set above or in
# the config file) _or_ with the 'built in' default search
# paths. This is the prefered way.
"$ZPOOL" import -N "$pool" 2> /dev/null
r="$?" ; RET=$((RET + r))
if [ "$r" -eq 0 ]
then
# Output success and process the next pool
[ -z "$init" ] && zfs_log_end_msg 0
continue
fi
# We don't want a fail msg here, we're going to try import
# using the cache file soon and that might succeed.
[ ! -f "$ZPOOL_CACHE" ] && zfs_log_end_msg "$RET"
if [ "$r" -gt 0 -a -f "$ZPOOL_CACHE" ]
then
# Failed to import without a cache file. Try WITH...
if [ -z "$init" -a "$VERBOSE_MOUNT" = 'yes' ]
then
# Interactive + Verbose = more information
zfs_log_progress_msg " using cache file"
fi
"$ZPOOL" import -c "$ZPOOL_CACHE" -N "$pool" 2> /dev/null
r="$?" ; RET=$((RET + r))
if [ "$r" -eq 0 ]
then
[ -z "$init" ] && zfs_log_end_msg 0
continue 3 # Next pool
fi
zfs_log_end_msg "$RET"
fi
done
[ -n "$init" ] && zfs_log_end_msg "$RET"
IFS="$OLD_IFS"
[ -n "$already_imported" -a -z "$available_pools" ] && return 0
return "$RET"
}
# Export all pools
do_export()
{
local pool root_pool RET r
RET=0
root_pool=$(get_root_pool)
[ -n "$init" ] && zfs_log_begin_msg "Exporting ZFS pool(s)"
TMPFILE=$(mktemp --tmpdir=/var/tmp zpool.XXXXX)
"$ZPOOL" list -H -oname > "$TMPFILE"
while read pool; do
[ "$pool" = "$root_pool" ] && continue
if [ -z "$init" ]
then
# Interactive - one 'Importing ...' line per pool
zfs_log_begin_msg "Exporting ZFS pool $pool"
else
# Not interactive - a dot for each pool.
zfs_log_progress_msg "."
fi
"$ZPOOL" export "$pool"
r="$?" ; RET=$((RET + r))
[ -z "$init" ] && zfs_log_end_msg "$r"
done < "$TMPFILE"
rm -f "$TMPFILE"
[ -n "$init" ] && zfs_log_end_msg "$RET"
}
# Output the status and list of pools
do_status()
{
check_module_loaded "zfs" || exit 0
"$ZPOOL" status && echo "" && "$ZPOOL" list
}
do_start()
{
if [ "$VERBOSE_MOUNT" = 'yes' ]
then
zfs_log_begin_msg "Checking if ZFS userspace tools present"
fi
if checksystem
then
[ "$VERBOSE_MOUNT" = 'yes' ] && zfs_log_end_msg 0
if [ "$VERBOSE_MOUNT" = 'yes' ]
then
zfs_log_begin_msg "Loading kernel ZFS infrastructure"
fi
if ! load_module "zfs"
then
[ "$VERBOSE_MOUNT" = 'yes' ] && zfs_log_end_msg 1
return 5
fi
[ "$VERBOSE_MOUNT" = 'yes' ] && zfs_log_end_msg 0
do_import && udev_trigger # just to make sure we get zvols.
return 0
else
return 1
fi
}
do_stop()
{
# Check to see if the module is even loaded.
check_module_loaded "zfs" || exit 0
do_export
}
# ----------------------------------------------------
if [ ! -e /etc/gentoo-release ]
then
case "$1" in
start)
do_start
;;
stop)
do_stop
;;
status)
do_status
;;
force-reload|condrestart|reload|restart)
# no-op
;;
*)
[ -n "$1" ] && echo "Error: Unknown command $1."
echo "Usage: $0 {start|stop|status}"
exit 3
;;
esac
exit $?
else
# Create wrapper functions since Gentoo don't use the case part.
depend() { do_depend; }
start() { do_start; }
stop() { do_stop; }
status() { do_status; }
fi