340 lines
8.3 KiB
Bash
Executable file
340 lines
8.3 KiB
Bash
Executable file
#!/bin/sh
|
|
#
|
|
# zfs-import This script will import ZFS pools
|
|
#
|
|
# chkconfig: 2345 01 99
|
|
# description: This script will perform a verbatim import of ZFS pools
|
|
# during system boot.
|
|
# probe: true
|
|
#
|
|
### BEGIN INIT INFO
|
|
# Provides: zfs-import
|
|
# Required-Start: mtab
|
|
# Required-Stop: $local_fs mtab
|
|
# 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` command.
|
|
### END INIT INFO
|
|
#
|
|
# NOTE: Not having '$local_fs' on Required-Start but only on Required-Stop
|
|
# is on purpose. If we have '$local_fs' in both (and X-Start-Before=checkfs)
|
|
# we get conflicts - import needs to be started extremely early,
|
|
# but not stopped too late.
|
|
#
|
|
# 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
|
|
. /usr/local/etc/zfs/zfs-functions
|
|
|
|
# ----------------------------------------------------
|
|
|
|
do_depend()
|
|
{
|
|
before swap
|
|
after sysfs udev
|
|
keyword -lxc -openvz -prefix -vserver
|
|
}
|
|
|
|
# Use the zpool cache file to import pools
|
|
do_verbatim_import()
|
|
{
|
|
if [ -f "$ZPOOL_CACHE" ]
|
|
then
|
|
zfs_action "Importing ZFS pool(s)" \
|
|
"$ZPOOL" import -c "$ZPOOL_CACHE" -N -a
|
|
fi
|
|
}
|
|
|
|
# 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 ';'.
|
|
}
|
|
|
|
# Find and import all visible pools, even exported ones
|
|
do_import_all_visible()
|
|
{
|
|
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 visible/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 'normally', 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 compatibility, 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 want 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 available 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 preferred way.
|
|
"$ZPOOL" import -N ${ZPOOL_IMPORT_OPTS} "$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" ] && check_boolean "$VERBOSE_MOUNT"
|
|
then
|
|
# Interactive + Verbose = more information
|
|
zfs_log_progress_msg " using cache file"
|
|
fi
|
|
|
|
"$ZPOOL" import -c "$ZPOOL_CACHE" -N ${ZPOOL_IMPORT_OPTS} \
|
|
"$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"
|
|
}
|
|
|
|
do_import()
|
|
{
|
|
if check_boolean "$ZPOOL_IMPORT_ALL_VISIBLE"
|
|
then
|
|
do_import_all_visible
|
|
else
|
|
# This is the default option
|
|
do_verbatim_import
|
|
fi
|
|
}
|
|
|
|
# Output the status and list of pools
|
|
do_status()
|
|
{
|
|
check_module_loaded "zfs" || exit 0
|
|
|
|
"$ZPOOL" status && echo "" && "$ZPOOL" list
|
|
}
|
|
|
|
do_start()
|
|
{
|
|
if check_boolean "$VERBOSE_MOUNT"
|
|
then
|
|
zfs_log_begin_msg "Checking if ZFS userspace tools present"
|
|
fi
|
|
|
|
if checksystem
|
|
then
|
|
check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0
|
|
|
|
check_boolean "$VERBOSE_MOUNT" && \
|
|
zfs_log_begin_msg "Loading kernel ZFS infrastructure"
|
|
|
|
if ! load_module "zfs"
|
|
then
|
|
check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 1
|
|
return 5
|
|
fi
|
|
check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0
|
|
|
|
do_import && udev_trigger # just to make sure we get zvols.
|
|
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ----------------------------------------------------
|
|
|
|
if [ ! -e /sbin/openrc-run ]
|
|
then
|
|
case "$1" in
|
|
start)
|
|
do_start
|
|
;;
|
|
stop)
|
|
# no-op
|
|
;;
|
|
status)
|
|
do_status
|
|
;;
|
|
force-reload|condrestart|reload|restart)
|
|
# no-op
|
|
;;
|
|
*)
|
|
[ -n "$1" ] && echo "Error: Unknown command $1."
|
|
echo "Usage: $0 {start|status}"
|
|
exit 3
|
|
;;
|
|
esac
|
|
|
|
exit $?
|
|
else
|
|
# Create wrapper functions since Gentoo don't use the case part.
|
|
depend() { do_depend; }
|
|
start() { do_start; }
|
|
status() { do_status; }
|
|
fi
|