]> git.proxmox.com Git - mirror_zfs.git/blob - etc/init.d/zfs-import.in
etc/init.d: decide which variant to use at build time.
[mirror_zfs.git] / etc / init.d / zfs-import.in
1 #!@DEFAULT_INIT_SHELL@
2 # shellcheck disable=SC2154
3 #
4 # zfs-import This script will import ZFS pools
5 #
6 # chkconfig: 2345 01 99
7 # description: This script will perform a verbatim import of ZFS pools
8 # during system boot.
9 # probe: true
10 #
11 ### BEGIN INIT INFO
12 # Provides: zfs-import
13 # Required-Start: mtab
14 # Required-Stop: $local_fs mtab
15 # Default-Start: S
16 # Default-Stop: 0 1 6
17 # X-Start-Before: checkfs
18 # X-Stop-After: zfs-mount
19 # Short-Description: Import ZFS pools
20 # Description: Run the `zpool import` command.
21 ### END INIT INFO
22 #
23 # NOTE: Not having '$local_fs' on Required-Start but only on Required-Stop
24 # is on purpose. If we have '$local_fs' in both (and X-Start-Before=checkfs)
25 # we get conflicts - import needs to be started extremely early,
26 # but not stopped too late.
27 #
28 # Released under the 2-clause BSD license.
29 #
30 # This script is based on debian/zfsutils.zfs.init from the
31 # Debian GNU/kFreeBSD zfsutils 8.1-3 package, written by Aurelien Jarno.
32
33 # Source the common init script
34 . @sysconfdir@/zfs/zfs-functions
35
36 # ----------------------------------------------------
37
38 do_depend()
39 {
40 before swap
41 after sysfs udev
42 keyword -lxc -openvz -prefix -vserver
43 }
44
45 # Use the zpool cache file to import pools
46 do_verbatim_import()
47 {
48 if [ -f "$ZPOOL_CACHE" ]
49 then
50 zfs_action "Importing ZFS pool(s)" \
51 "$ZPOOL" import -c "$ZPOOL_CACHE" -N -a
52 fi
53 }
54
55 # Support function to get a list of all pools, separated with ';'
56 find_pools()
57 {
58 local pools
59
60 pools=$("$@" 2> /dev/null | \
61 sed -Ee '/pool:|^[a-zA-Z0-9]/!d' -e '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
69 do_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
260 do_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
272 do_status()
273 {
274 check_module_loaded "zfs" || exit 0
275
276 "$ZPOOL" status && echo "" && "$ZPOOL" list
277 }
278
279 do_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
310 if @IS_SYSV_RC@
311 then
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 $?
333 else
334 # Create wrapper functions since Gentoo don't use the case part.
335 depend() { do_depend; }
336 start() { do_start; }
337 status() { do_status; }
338 fi