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