1eda14cbcSMatt Macy#!@DEFAULT_INIT_SHELL@ 2eda14cbcSMatt Macy# 3eda14cbcSMatt Macy# zfs-import This script will import ZFS pools 4eda14cbcSMatt Macy# 5eda14cbcSMatt Macy# chkconfig: 2345 01 99 6eda14cbcSMatt Macy# description: This script will perform a verbatim import of ZFS pools 7eda14cbcSMatt Macy# during system boot. 8eda14cbcSMatt Macy# probe: true 9eda14cbcSMatt Macy# 10eda14cbcSMatt Macy### BEGIN INIT INFO 11eda14cbcSMatt Macy# Provides: zfs-import 12eda14cbcSMatt Macy# Required-Start: mtab 13eda14cbcSMatt Macy# Required-Stop: $local_fs mtab 14eda14cbcSMatt Macy# Default-Start: S 15eda14cbcSMatt Macy# Default-Stop: 0 1 6 16eda14cbcSMatt Macy# X-Start-Before: checkfs 17eda14cbcSMatt Macy# X-Stop-After: zfs-mount 18eda14cbcSMatt Macy# Short-Description: Import ZFS pools 19eda14cbcSMatt Macy# Description: Run the `zpool import` command. 20eda14cbcSMatt Macy### END INIT INFO 21eda14cbcSMatt Macy# 22eda14cbcSMatt Macy# NOTE: Not having '$local_fs' on Required-Start but only on Required-Stop 23eda14cbcSMatt Macy# is on purpose. If we have '$local_fs' in both (and X-Start-Before=checkfs) 24eda14cbcSMatt Macy# we get conflicts - import needs to be started extremely early, 25eda14cbcSMatt Macy# but not stopped too late. 26eda14cbcSMatt Macy# 27eda14cbcSMatt Macy# Released under the 2-clause BSD license. 28eda14cbcSMatt Macy# 2916038816SMartin Matuska# This script is based on debian/zfsutils.zfs.init from the 3016038816SMartin Matuska# Debian GNU/kFreeBSD zfsutils 8.1-3 package, written by Aurelien Jarno. 31eda14cbcSMatt Macy 32eda14cbcSMatt Macy# Source the common init script 33eda14cbcSMatt Macy. @sysconfdir@/zfs/zfs-functions 34eda14cbcSMatt Macy 35eda14cbcSMatt Macy# ---------------------------------------------------- 36eda14cbcSMatt Macy 37eda14cbcSMatt Macydo_depend() 38eda14cbcSMatt Macy{ 39eda14cbcSMatt Macy before swap 40eda14cbcSMatt Macy after sysfs udev 41eda14cbcSMatt Macy keyword -lxc -openvz -prefix -vserver 42eda14cbcSMatt Macy} 43eda14cbcSMatt Macy 44eda14cbcSMatt Macy# Use the zpool cache file to import pools 45eda14cbcSMatt Macydo_verbatim_import() 46eda14cbcSMatt Macy{ 47eda14cbcSMatt Macy if [ -f "$ZPOOL_CACHE" ] 48eda14cbcSMatt Macy then 49eda14cbcSMatt Macy zfs_action "Importing ZFS pool(s)" \ 50eda14cbcSMatt Macy "$ZPOOL" import -c "$ZPOOL_CACHE" -N -a 51eda14cbcSMatt Macy fi 52eda14cbcSMatt Macy} 53eda14cbcSMatt Macy 54eda14cbcSMatt Macy# Support function to get a list of all pools, separated with ';' 55eda14cbcSMatt Macyfind_pools() 56eda14cbcSMatt Macy{ 57eda14cbcSMatt Macy local pools 58eda14cbcSMatt Macy 5916038816SMartin Matuska pools=$("$@" 2> /dev/null | \ 60*dae17134SMartin Matuska sed -Ee '/pool:|^[a-zA-Z0-9]/!d' -e 's@.*: @@' | \ 61eda14cbcSMatt Macy sort | \ 6216038816SMartin Matuska tr '\n' ';') 63eda14cbcSMatt Macy 64eda14cbcSMatt Macy echo "${pools%%;}" # Return without the last ';'. 65eda14cbcSMatt Macy} 66eda14cbcSMatt Macy 67eda14cbcSMatt Macy# Find and import all visible pools, even exported ones 68eda14cbcSMatt Macydo_import_all_visible() 69eda14cbcSMatt Macy{ 70eda14cbcSMatt Macy local already_imported available_pools pool npools 71eda14cbcSMatt Macy local exception dir ZPOOL_IMPORT_PATH RET=0 r=1 72eda14cbcSMatt Macy 73eda14cbcSMatt Macy # In case not shutdown cleanly. 7416038816SMartin Matuska # shellcheck disable=SC2154 75eda14cbcSMatt Macy [ -n "$init" ] && rm -f /etc/dfs/sharetab 76eda14cbcSMatt Macy 77eda14cbcSMatt Macy # Just simplify code later on. 7816038816SMartin Matuska if [ -n "$USE_DISK_BY_ID" ] && [ "$USE_DISK_BY_ID" != 'yes' ] 79eda14cbcSMatt Macy then 80eda14cbcSMatt Macy # It's something, but not 'yes' so it's no good to us. 81eda14cbcSMatt Macy unset USE_DISK_BY_ID 82eda14cbcSMatt Macy fi 83eda14cbcSMatt Macy 84eda14cbcSMatt Macy # Find list of already imported pools. 85eda14cbcSMatt Macy already_imported=$(find_pools "$ZPOOL" list -H -oname) 86eda14cbcSMatt Macy available_pools=$(find_pools "$ZPOOL" import) 87eda14cbcSMatt Macy 88eda14cbcSMatt Macy # Just in case - seen it happen (that a pool isn't visible/found 89eda14cbcSMatt Macy # with a simple "zpool import" but only when using the "-d" 90eda14cbcSMatt Macy # option or setting ZPOOL_IMPORT_PATH). 91eda14cbcSMatt Macy if [ -d "/dev/disk/by-id" ] 92eda14cbcSMatt Macy then 93eda14cbcSMatt Macy npools=$(find_pools "$ZPOOL" import -d /dev/disk/by-id) 94eda14cbcSMatt Macy if [ -n "$npools" ] 95eda14cbcSMatt Macy then 96eda14cbcSMatt Macy # Because we have found extra pool(s) here, which wasn't 97eda14cbcSMatt Macy # found 'normally', we need to force USE_DISK_BY_ID to 98eda14cbcSMatt Macy # make sure we're able to actually import it/them later. 99eda14cbcSMatt Macy USE_DISK_BY_ID='yes' 100eda14cbcSMatt Macy 101eda14cbcSMatt Macy if [ -n "$available_pools" ] 102eda14cbcSMatt Macy then 103eda14cbcSMatt Macy # Filter out duplicates (pools found with the simpl 104eda14cbcSMatt Macy # "zpool import" but which is also found with the 105eda14cbcSMatt Macy # "zpool import -d ..."). 106eda14cbcSMatt Macy npools=$(echo "$npools" | sed "s,$available_pools,,") 107eda14cbcSMatt Macy 108eda14cbcSMatt Macy # Add the list to the existing list of 109eda14cbcSMatt Macy # available pools 110eda14cbcSMatt Macy available_pools="$available_pools;$npools" 111eda14cbcSMatt Macy else 112eda14cbcSMatt Macy available_pools="$npools" 113eda14cbcSMatt Macy fi 114eda14cbcSMatt Macy fi 115eda14cbcSMatt Macy fi 116eda14cbcSMatt Macy 117eda14cbcSMatt Macy # Filter out any exceptions... 118eda14cbcSMatt Macy if [ -n "$ZFS_POOL_EXCEPTIONS" ] 119eda14cbcSMatt Macy then 120eda14cbcSMatt Macy local found="" 121eda14cbcSMatt Macy local apools="" 122eda14cbcSMatt Macy OLD_IFS="$IFS" ; IFS=";" 123eda14cbcSMatt Macy 124eda14cbcSMatt Macy for pool in $available_pools 125eda14cbcSMatt Macy do 126eda14cbcSMatt Macy for exception in $ZFS_POOL_EXCEPTIONS 127eda14cbcSMatt Macy do 128eda14cbcSMatt Macy [ "$pool" = "$exception" ] && continue 2 129eda14cbcSMatt Macy found="$pool" 130eda14cbcSMatt Macy done 131eda14cbcSMatt Macy 132eda14cbcSMatt Macy if [ -n "$found" ] 133eda14cbcSMatt Macy then 134eda14cbcSMatt Macy if [ -n "$apools" ] 135eda14cbcSMatt Macy then 136eda14cbcSMatt Macy apools="$apools;$pool" 137eda14cbcSMatt Macy else 138eda14cbcSMatt Macy apools="$pool" 139eda14cbcSMatt Macy fi 140eda14cbcSMatt Macy fi 141eda14cbcSMatt Macy done 142eda14cbcSMatt Macy 143eda14cbcSMatt Macy IFS="$OLD_IFS" 144eda14cbcSMatt Macy available_pools="$apools" 145eda14cbcSMatt Macy fi 146eda14cbcSMatt Macy 147eda14cbcSMatt Macy # For backwards compatibility, make sure that ZPOOL_IMPORT_PATH is set 148eda14cbcSMatt Macy # to something we can use later with the real import(s). We want to 149eda14cbcSMatt Macy # make sure we find all by* dirs, BUT by-vdev should be first (if it 150eda14cbcSMatt Macy # exists). 15116038816SMartin Matuska if [ -n "$USE_DISK_BY_ID" ] && [ -z "$ZPOOL_IMPORT_PATH" ] 152eda14cbcSMatt Macy then 153eda14cbcSMatt Macy local dirs 154eda14cbcSMatt Macy dirs="$(for dir in $(echo /dev/disk/by-*) 155eda14cbcSMatt Macy do 156eda14cbcSMatt Macy # Ignore by-vdev here - we want it first! 157eda14cbcSMatt Macy echo "$dir" | grep -q /by-vdev && continue 158eda14cbcSMatt Macy [ ! -d "$dir" ] && continue 159eda14cbcSMatt Macy 16016038816SMartin Matuska printf "%s" "$dir:" 161eda14cbcSMatt Macy done | sed 's,:$,,g')" 162eda14cbcSMatt Macy 163eda14cbcSMatt Macy if [ -d "/dev/disk/by-vdev" ] 164eda14cbcSMatt Macy then 165eda14cbcSMatt Macy # Add by-vdev at the beginning. 166eda14cbcSMatt Macy ZPOOL_IMPORT_PATH="/dev/disk/by-vdev:" 167eda14cbcSMatt Macy fi 168eda14cbcSMatt Macy 169eda14cbcSMatt Macy # Help with getting LUKS partitions etc imported. 170eda14cbcSMatt Macy if [ -d "/dev/mapper" ]; then 171eda14cbcSMatt Macy if [ -n "$ZPOOL_IMPORT_PATH" ]; then 172eda14cbcSMatt Macy ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH:/dev/mapper:" 173eda14cbcSMatt Macy else 174eda14cbcSMatt Macy ZPOOL_IMPORT_PATH="/dev/mapper:" 175eda14cbcSMatt Macy fi 176eda14cbcSMatt Macy fi 177eda14cbcSMatt Macy 178eda14cbcSMatt Macy # ... and /dev at the very end, just for good measure. 179eda14cbcSMatt Macy ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH$dirs:/dev" 180eda14cbcSMatt Macy fi 181eda14cbcSMatt Macy 182eda14cbcSMatt Macy # Needs to be exported for "zpool" to catch it. 183eda14cbcSMatt Macy [ -n "$ZPOOL_IMPORT_PATH" ] && export ZPOOL_IMPORT_PATH 184eda14cbcSMatt Macy 185eda14cbcSMatt Macy # Mount all available pools (except those set in ZFS_POOL_EXCEPTIONS. 186eda14cbcSMatt Macy # 187eda14cbcSMatt Macy # If not interactive (run from init - variable init='/sbin/init') 188eda14cbcSMatt Macy # we get ONE line for all pools being imported, with just a dot 189eda14cbcSMatt Macy # as status for each pool. 190eda14cbcSMatt Macy # Example: Importing ZFS pool(s)... [OK] 191eda14cbcSMatt Macy # 192eda14cbcSMatt Macy # If it IS interactive (started from the shell manually), then we 193eda14cbcSMatt Macy # get one line per pool importing. 194eda14cbcSMatt Macy # Example: Importing ZFS pool pool1 [OK] 195eda14cbcSMatt Macy # Importing ZFS pool pool2 [OK] 196eda14cbcSMatt Macy # [etc] 197eda14cbcSMatt Macy [ -n "$init" ] && zfs_log_begin_msg "Importing ZFS pool(s)" 198eda14cbcSMatt Macy OLD_IFS="$IFS" ; IFS=";" 199eda14cbcSMatt Macy for pool in $available_pools 200eda14cbcSMatt Macy do 201eda14cbcSMatt Macy [ -z "$pool" ] && continue 202eda14cbcSMatt Macy 203eda14cbcSMatt Macy # We have pools that haven't been imported - import them 204eda14cbcSMatt Macy if [ -n "$init" ] 205eda14cbcSMatt Macy then 206eda14cbcSMatt Macy # Not interactive - a dot for each pool. 207eda14cbcSMatt Macy # Except on Gentoo where this doesn't work. 208eda14cbcSMatt Macy zfs_log_progress_msg "." 209eda14cbcSMatt Macy else 210eda14cbcSMatt Macy # Interactive - one 'Importing ...' line per pool 211eda14cbcSMatt Macy zfs_log_begin_msg "Importing ZFS pool $pool" 212eda14cbcSMatt Macy fi 213eda14cbcSMatt Macy 214eda14cbcSMatt Macy # Import by using ZPOOL_IMPORT_PATH (either set above or in 215eda14cbcSMatt Macy # the config file) _or_ with the 'built in' default search 216eda14cbcSMatt Macy # paths. This is the preferred way. 21716038816SMartin Matuska # shellcheck disable=SC2086 218eda14cbcSMatt Macy "$ZPOOL" import -N ${ZPOOL_IMPORT_OPTS} "$pool" 2> /dev/null 219eda14cbcSMatt Macy r="$?" ; RET=$((RET + r)) 220eda14cbcSMatt Macy if [ "$r" -eq 0 ] 221eda14cbcSMatt Macy then 222eda14cbcSMatt Macy # Output success and process the next pool 223eda14cbcSMatt Macy [ -z "$init" ] && zfs_log_end_msg 0 224eda14cbcSMatt Macy continue 225eda14cbcSMatt Macy fi 226eda14cbcSMatt Macy # We don't want a fail msg here, we're going to try import 227eda14cbcSMatt Macy # using the cache file soon and that might succeed. 228eda14cbcSMatt Macy [ ! -f "$ZPOOL_CACHE" ] && zfs_log_end_msg "$RET" 229eda14cbcSMatt Macy 23016038816SMartin Matuska if [ "$r" -gt 0 ] && [ -f "$ZPOOL_CACHE" ] 231eda14cbcSMatt Macy then 232eda14cbcSMatt Macy # Failed to import without a cache file. Try WITH... 233eda14cbcSMatt Macy if [ -z "$init" ] && check_boolean "$VERBOSE_MOUNT" 234eda14cbcSMatt Macy then 235eda14cbcSMatt Macy # Interactive + Verbose = more information 236eda14cbcSMatt Macy zfs_log_progress_msg " using cache file" 237eda14cbcSMatt Macy fi 238eda14cbcSMatt Macy 23916038816SMartin Matuska # shellcheck disable=SC2086 240eda14cbcSMatt Macy "$ZPOOL" import -c "$ZPOOL_CACHE" -N ${ZPOOL_IMPORT_OPTS} \ 241eda14cbcSMatt Macy "$pool" 2> /dev/null 242eda14cbcSMatt Macy r="$?" ; RET=$((RET + r)) 243eda14cbcSMatt Macy if [ "$r" -eq 0 ] 244eda14cbcSMatt Macy then 245eda14cbcSMatt Macy [ -z "$init" ] && zfs_log_end_msg 0 246eda14cbcSMatt Macy continue 3 # Next pool 247eda14cbcSMatt Macy fi 248eda14cbcSMatt Macy zfs_log_end_msg "$RET" 249eda14cbcSMatt Macy fi 250eda14cbcSMatt Macy done 251eda14cbcSMatt Macy [ -n "$init" ] && zfs_log_end_msg "$RET" 252eda14cbcSMatt Macy 253eda14cbcSMatt Macy IFS="$OLD_IFS" 25416038816SMartin Matuska [ -n "$already_imported" ] && [ -z "$available_pools" ] && return 0 255eda14cbcSMatt Macy 256eda14cbcSMatt Macy return "$RET" 257eda14cbcSMatt Macy} 258eda14cbcSMatt Macy 259eda14cbcSMatt Macydo_import() 260eda14cbcSMatt Macy{ 261eda14cbcSMatt Macy if check_boolean "$ZPOOL_IMPORT_ALL_VISIBLE" 262eda14cbcSMatt Macy then 263eda14cbcSMatt Macy do_import_all_visible 264eda14cbcSMatt Macy else 265eda14cbcSMatt Macy # This is the default option 266eda14cbcSMatt Macy do_verbatim_import 267eda14cbcSMatt Macy fi 268eda14cbcSMatt Macy} 269eda14cbcSMatt Macy 270eda14cbcSMatt Macy# Output the status and list of pools 271eda14cbcSMatt Macydo_status() 272eda14cbcSMatt Macy{ 273eda14cbcSMatt Macy check_module_loaded "zfs" || exit 0 274eda14cbcSMatt Macy 275eda14cbcSMatt Macy "$ZPOOL" status && echo "" && "$ZPOOL" list 276eda14cbcSMatt Macy} 277eda14cbcSMatt Macy 278eda14cbcSMatt Macydo_start() 279eda14cbcSMatt Macy{ 280eda14cbcSMatt Macy if check_boolean "$VERBOSE_MOUNT" 281eda14cbcSMatt Macy then 282eda14cbcSMatt Macy zfs_log_begin_msg "Checking if ZFS userspace tools present" 283eda14cbcSMatt Macy fi 284eda14cbcSMatt Macy 285eda14cbcSMatt Macy if checksystem 286eda14cbcSMatt Macy then 287eda14cbcSMatt Macy check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0 288eda14cbcSMatt Macy 289eda14cbcSMatt Macy check_boolean "$VERBOSE_MOUNT" && \ 290eda14cbcSMatt Macy zfs_log_begin_msg "Loading kernel ZFS infrastructure" 291eda14cbcSMatt Macy 292eda14cbcSMatt Macy if ! load_module "zfs" 293eda14cbcSMatt Macy then 294eda14cbcSMatt Macy check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 1 295eda14cbcSMatt Macy return 5 296eda14cbcSMatt Macy fi 297eda14cbcSMatt Macy check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0 298eda14cbcSMatt Macy 299eda14cbcSMatt Macy do_import && udev_trigger # just to make sure we get zvols. 300eda14cbcSMatt Macy 301eda14cbcSMatt Macy return 0 302eda14cbcSMatt Macy else 303eda14cbcSMatt Macy return 1 304eda14cbcSMatt Macy fi 305eda14cbcSMatt Macy} 306eda14cbcSMatt Macy 307eda14cbcSMatt Macy# ---------------------------------------------------- 308eda14cbcSMatt Macy 309eda14cbcSMatt Macyif [ ! -e /sbin/openrc-run ] 310eda14cbcSMatt Macythen 311eda14cbcSMatt Macy case "$1" in 312eda14cbcSMatt Macy start) 313eda14cbcSMatt Macy do_start 314eda14cbcSMatt Macy ;; 315eda14cbcSMatt Macy stop) 316eda14cbcSMatt Macy # no-op 317eda14cbcSMatt Macy ;; 318eda14cbcSMatt Macy status) 319eda14cbcSMatt Macy do_status 320eda14cbcSMatt Macy ;; 321eda14cbcSMatt Macy force-reload|condrestart|reload|restart) 322eda14cbcSMatt Macy # no-op 323eda14cbcSMatt Macy ;; 324eda14cbcSMatt Macy *) 325eda14cbcSMatt Macy [ -n "$1" ] && echo "Error: Unknown command $1." 326eda14cbcSMatt Macy echo "Usage: $0 {start|status}" 327eda14cbcSMatt Macy exit 3 328eda14cbcSMatt Macy ;; 329eda14cbcSMatt Macy esac 330eda14cbcSMatt Macy 331eda14cbcSMatt Macy exit $? 332eda14cbcSMatt Macyelse 333eda14cbcSMatt Macy # Create wrapper functions since Gentoo don't use the case part. 334eda14cbcSMatt Macy depend() { do_depend; } 335eda14cbcSMatt Macy start() { do_start; } 336eda14cbcSMatt Macy status() { do_status; } 337eda14cbcSMatt Macyfi 338