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