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