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