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 grep -E "pool:|^[a-zA-Z0-9]" | \ 61 sed '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