3 # zfs-import This script will import ZFS pools
5 # chkconfig: 2345 01 99
6 # description: This script will perform a verbatim import of ZFS pools
11 # Provides: zfs-import
12 # Required-Start: mtab
13 # Required-Stop: $local_fs mtab
16 # X-Start-Before: checkfs
17 # X-Stop-After: zfs-mount
18 # Short-Description: Import ZFS pools
19 # Description: Run the `zpool import` command.
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.
27 # Released under the 2-clause BSD license.
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
34 # Source the common init script
35 . @sysconfdir@/zfs/zfs-functions
37 # ----------------------------------------------------
43 keyword -lxc -openvz -prefix -vserver
46 # Use the zpool cache file to import pools
49 if [ -f "$ZPOOL_CACHE" ]
51 zfs_action "Importing ZFS pool(s)" \
52 "$ZPOOL" import -c "$ZPOOL_CACHE" -N -a
56 # Support function to get a list of all pools, separated with ';'
62 pools=$($CMD 2> /dev/null | \
63 grep -E "pool:|^[a-zA-Z0-9]" | \
70 echo "${pools%%;}" # Return without the last ';'.
73 # Find and import all visible pools, even exported ones
74 do_import_all_visible()
76 local already_imported available_pools pool npools
77 local exception dir ZPOOL_IMPORT_PATH RET=0 r=1
79 # In case not shutdown cleanly.
80 [ -n "$init" ] && rm -f /etc/dfs/sharetab
82 # Just simplify code later on.
83 if [ -n "$USE_DISK_BY_ID" -a "$USE_DISK_BY_ID" != 'yes' ]
85 # It's something, but not 'yes' so it's no good to us.
89 # Find list of already imported pools.
90 already_imported=$(find_pools "$ZPOOL" list -H -oname)
91 available_pools=$(find_pools "$ZPOOL" import)
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" ]
98 npools=$(find_pools "$ZPOOL" import -d /dev/disk/by-id)
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.
106 if [ -n "$available_pools" ]
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,,")
113 # Add the list to the existing list of
115 available_pools="$available_pools;$npools"
117 available_pools="$npools"
122 # Filter out any exceptions...
123 if [ -n "$ZFS_POOL_EXCEPTIONS" ]
127 OLD_IFS="$IFS" ; IFS=";"
129 for pool in $available_pools
131 for exception in $ZFS_POOL_EXCEPTIONS
133 [ "$pool" = "$exception" ] && continue 2
141 apools="$apools;$pool"
149 available_pools="$apools"
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
156 if [ -n "$USE_DISK_BY_ID" -a -z "$ZPOOL_IMPORT_PATH" ]
159 dirs="$(for dir in $(echo /dev/disk/by-*)
161 # Ignore by-vdev here - we want it first!
162 echo "$dir" | grep -q /by-vdev && continue
163 [ ! -d "$dir" ] && continue
166 done | sed 's,:$,,g')"
168 if [ -d "/dev/disk/by-vdev" ]
170 # Add by-vdev at the beginning.
171 ZPOOL_IMPORT_PATH="/dev/disk/by-vdev:"
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:"
179 ZPOOL_IMPORT_PATH="/dev/mapper:"
183 # ... and /dev at the very end, just for good measure.
184 ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH$dirs:/dev"
187 # Needs to be exported for "zpool" to catch it.
188 [ -n "$ZPOOL_IMPORT_PATH" ] && export ZPOOL_IMPORT_PATH
190 # Mount all available pools (except those set in ZFS_POOL_EXCEPTIONS.
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]
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]
202 [ -n "$init" ] && zfs_log_begin_msg "Importing ZFS pool(s)"
203 OLD_IFS="$IFS" ; IFS=";"
204 for pool in $available_pools
206 [ -z "$pool" ] && continue
208 # We have pools that haven't been imported - import them
211 # Not interactive - a dot for each pool.
212 # Except on Gentoo where this doesn't work.
213 zfs_log_progress_msg "."
215 # Interactive - one 'Importing ...' line per pool
216 zfs_log_begin_msg "Importing ZFS pool $pool"
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))
226 # Output success and process the next pool
227 [ -z "$init" ] && zfs_log_end_msg 0
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"
234 if [ "$r" -gt 0 -a -f "$ZPOOL_CACHE" ]
236 # Failed to import without a cache file. Try WITH...
237 if [ -z "$init" ] && check_boolean "$VERBOSE_MOUNT"
239 # Interactive + Verbose = more information
240 zfs_log_progress_msg " using cache file"
243 "$ZPOOL" import -c "$ZPOOL_CACHE" -N ${ZPOOL_IMPORT_OPTS} \
245 r="$?" ; RET=$((RET + r))
248 [ -z "$init" ] && zfs_log_end_msg 0
249 continue 3 # Next pool
251 zfs_log_end_msg "$RET"
254 [ -n "$init" ] && zfs_log_end_msg "$RET"
257 [ -n "$already_imported" -a -z "$available_pools" ] && return 0
264 if check_boolean "$ZPOOL_IMPORT_ALL_VISIBLE"
266 do_import_all_visible
268 # This is the default option
273 # Output the status and list of pools
276 check_module_loaded "zfs" || exit 0
278 "$ZPOOL" status && echo "" && "$ZPOOL" list
283 if check_boolean "$VERBOSE_MOUNT"
285 zfs_log_begin_msg "Checking if ZFS userspace tools present"
290 check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0
292 check_boolean "$VERBOSE_MOUNT" && \
293 zfs_log_begin_msg "Loading kernel ZFS infrastructure"
295 if ! load_module "zfs"
297 check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 1
300 check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0
302 do_import && udev_trigger # just to make sure we get zvols.
310 # ----------------------------------------------------
312 if [ ! -e /sbin/openrc-run ]
324 force-reload|condrestart|reload|restart)
328 [ -n "$1" ] && echo "Error: Unknown command $1."
329 echo "Usage: $0 {start|status}"
336 # Create wrapper functions since Gentoo don't use the case part.
337 depend() { do_depend; }
338 start() { do_start; }
339 status() { do_status; }