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