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