Avoid small buffer copying on write
[zfs.git] / etc / init.d / zfs-import.in
blobe4bc7b8339fcee601716a816d739bc08d1179132
1 #!@DEFAULT_INIT_SHELL@
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
7 #               during system boot.
8 # probe: true
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
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 # This script is based on debian/zfsutils.zfs.init from the
30 # Debian GNU/kFreeBSD zfsutils 8.1-3 package, written by Aurelien Jarno.
32 # Source the common init script
33 . @sysconfdir@/zfs/zfs-functions
35 # ----------------------------------------------------
37 do_depend()
39         before swap
40         after sysfs udev
41         keyword -lxc -openvz -prefix -vserver
44 # Use the zpool cache file to import pools
45 do_verbatim_import()
47         if [ -f "$ZPOOL_CACHE" ]
48         then
49                 zfs_action "Importing ZFS pool(s)" \
50                         "$ZPOOL" import -c "$ZPOOL_CACHE" -N -a
51         fi
54 # Support function to get a list of all pools, separated with ';'
55 find_pools()
57         local pools
59         pools=$("$@" 2> /dev/null | \
60                 grep -E "pool:|^[a-zA-Z0-9]" | \
61                 sed 's@.*: @@' | \
62                 sort | \
63                 tr '\n' ';')
65         echo "${pools%%;}" # Return without the last ';'.
68 # Find and import all visible pools, even exported ones
69 do_import_all_visible()
71         local already_imported available_pools pool npools
72         local exception dir ZPOOL_IMPORT_PATH RET=0 r=1
74         # In case not shutdown cleanly.
75         # shellcheck disable=SC2154
76         [ -n "$init" ] && rm -f /etc/dfs/sharetab
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
85         # Find list of already imported pools.
86         already_imported=$(find_pools "$ZPOOL" list -H -oname)
87         available_pools=$(find_pools "$ZPOOL" import)
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'
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,,")
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
118         # Filter out any exceptions...
119         if [ -n "$ZFS_POOL_EXCEPTIONS" ]
120         then
121                 local found=""
122                 local apools=""
123                 OLD_IFS="$IFS" ; IFS=";"
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
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
144                 IFS="$OLD_IFS"
145                 available_pools="$apools"
146         fi
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
161                         printf "%s" "$dir:"
162                 done | sed 's,:$,,g')"
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
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
179                 # ... and /dev at the very end, just for good measure.
180                 ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH$dirs:/dev"
181         fi
183         # Needs to be exported for "zpool" to catch it.
184         [ -n "$ZPOOL_IMPORT_PATH" ] && export ZPOOL_IMPORT_PATH
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
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
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"
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
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"
254         IFS="$OLD_IFS"
255         [ -n "$already_imported" ] && [ -z "$available_pools" ] && return 0
257         return "$RET"
260 do_import()
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
271 # Output the status and list of pools
272 do_status()
274         check_module_loaded "zfs" || exit 0
276         "$ZPOOL" status && echo "" && "$ZPOOL" list
279 do_start()
281         if check_boolean "$VERBOSE_MOUNT"
282         then
283             zfs_log_begin_msg "Checking if ZFS userspace tools present"
284         fi
286         if checksystem
287         then
288                 check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0
290                 check_boolean "$VERBOSE_MOUNT" && \
291                         zfs_log_begin_msg "Loading kernel ZFS infrastructure"
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
300                 do_import && udev_trigger # just to make sure we get zvols.
302                 return 0
303         else
304                 return 1
305         fi
308 # ----------------------------------------------------
310 if [ ! -e /sbin/openrc-run ]
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
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; }