]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - etc/init.d/zfs-import.in
Vendor import of openzfs master @ 184df27eef0abdc7ab2105b21257f753834b936b
[FreeBSD/FreeBSD.git] / etc / init.d / zfs-import.in
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
39 do_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
47 do_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 ';'
57 find_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
74 do_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
262 do_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
274 do_status()
275 {
276         check_module_loaded "zfs" || exit 0
277
278         "$ZPOOL" status && echo "" && "$ZPOOL" list
279 }
280
281 do_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
312 if [ ! -e /sbin/openrc-run ]
313 then
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 $?
335 else
336         # Create wrapper functions since Gentoo don't use the case part.
337         depend() { do_depend; }
338         start() { do_start; }
339         status() { do_status; }
340 fi