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