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