]>
Commit | Line | Data |
---|---|---|
e10b0808 AX |
1 | #!@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 | 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 CMD="$*" | |
59 | local pools | |
60 | ||
61 | pools=$($CMD 2> /dev/null | \ | |
62 | grep -E "pool:|^[a-zA-Z0-9]" | \ | |
63 | sed 's@.*: @@' | \ | |
64 | sort | \ | |
65 | while read pool; do \ | |
66 | echo -n "$pool;" | |
67 | done) | |
68 | ||
69 | echo "${pools%%;}" # Return without the last ';'. | |
70 | } | |
71 | ||
72 | # Find and import all visible pools, even exported ones | |
73 | do_import_all_visible() | |
74 | { | |
75 | local already_imported available_pools pool npools | |
76 | local exception dir ZPOOL_IMPORT_PATH RET=0 r=1 | |
77 | ||
78 | # In case not shutdown cleanly. | |
79 | [ -n "$init" ] && rm -f /etc/dfs/sharetab | |
80 | ||
81 | # Just simplify code later on. | |
82 | if [ -n "$USE_DISK_BY_ID" -a "$USE_DISK_BY_ID" != 'yes' ] | |
83 | then | |
84 | # It's something, but not 'yes' so it's no good to us. | |
85 | unset USE_DISK_BY_ID | |
86 | fi | |
87 | ||
88 | # Find list of already imported pools. | |
89 | already_imported=$(find_pools "$ZPOOL" list -H -oname) | |
90 | available_pools=$(find_pools "$ZPOOL" import) | |
91 | ||
92 | # Just in case - seen it happen (that a pool isn't visable/found | |
93 | # with a simple "zpool import" but only when using the "-d" | |
94 | # option or setting ZPOOL_IMPORT_PATH). | |
95 | if [ -d "/dev/disk/by-id" ] | |
96 | then | |
97 | npools=$(find_pools "$ZPOOL" import -d /dev/disk/by-id) | |
98 | if [ -n "$npools" ] | |
99 | then | |
100 | # Because we have found extra pool(s) here, which wasn't | |
cae5b340 | 101 | # found 'normally', we need to force USE_DISK_BY_ID to |
e10b0808 AX |
102 | # make sure we're able to actually import it/them later. |
103 | USE_DISK_BY_ID='yes' | |
104 | ||
105 | if [ -n "$available_pools" ] | |
106 | then | |
107 | # Filter out duplicates (pools found with the simpl | |
108 | # "zpool import" but which is also found with the | |
109 | # "zpool import -d ..."). | |
110 | npools=$(echo "$npools" | sed "s,$available_pools,,") | |
111 | ||
112 | # Add the list to the existing list of | |
113 | # available pools | |
114 | available_pools="$available_pools;$npools" | |
115 | else | |
116 | available_pools="$npools" | |
117 | fi | |
118 | fi | |
119 | fi | |
120 | ||
121 | # Filter out any exceptions... | |
122 | if [ -n "$ZFS_POOL_EXCEPTIONS" ] | |
123 | then | |
124 | local found="" | |
125 | local apools="" | |
126 | OLD_IFS="$IFS" ; IFS=";" | |
127 | ||
128 | for pool in $available_pools | |
129 | do | |
130 | for exception in $ZFS_POOL_EXCEPTIONS | |
131 | do | |
132 | [ "$pool" = "$exception" ] && continue 2 | |
133 | found="$pool" | |
134 | done | |
135 | ||
136 | if [ -n "$found" ] | |
137 | then | |
138 | if [ -n "$apools" ] | |
139 | then | |
140 | apools="$apools;$pool" | |
141 | else | |
142 | apools="$pool" | |
143 | fi | |
144 | fi | |
145 | done | |
146 | ||
147 | IFS="$OLD_IFS" | |
148 | available_pools="$apools" | |
149 | fi | |
150 | ||
cae5b340 | 151 | # For backwards compatibility, make sure that ZPOOL_IMPORT_PATH is set |
e10b0808 AX |
152 | # to something we can use later with the real import(s). We want to |
153 | # make sure we find all by* dirs, BUT by-vdev should be first (if it | |
154 | # exists). | |
155 | if [ -n "$USE_DISK_BY_ID" -a -z "$ZPOOL_IMPORT_PATH" ] | |
156 | then | |
157 | local dirs | |
158 | dirs="$(for dir in $(echo /dev/disk/by-*) | |
159 | do | |
cae5b340 | 160 | # Ignore by-vdev here - we want it first! |
e10b0808 AX |
161 | echo "$dir" | grep -q /by-vdev && continue |
162 | [ ! -d "$dir" ] && continue | |
163 | ||
164 | echo -n "$dir:" | |
165 | done | sed 's,:$,,g')" | |
166 | ||
167 | if [ -d "/dev/disk/by-vdev" ] | |
168 | then | |
169 | # Add by-vdev at the beginning. | |
170 | ZPOOL_IMPORT_PATH="/dev/disk/by-vdev:" | |
171 | fi | |
172 | ||
173 | # Help with getting LUKS partitions etc imported. | |
174 | if [ -d "/dev/mapper" ]; then | |
175 | if [ -n "$ZPOOL_IMPORT_PATH" ]; then | |
176 | ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH:/dev/mapper:" | |
177 | else | |
178 | ZPOOL_IMPORT_PATH="/dev/mapper:" | |
179 | fi | |
180 | fi | |
181 | ||
182 | # ... and /dev at the very end, just for good measure. | |
183 | ZPOOL_IMPORT_PATH="$ZPOOL_IMPORT_PATH$dirs:/dev" | |
184 | fi | |
185 | ||
186 | # Needs to be exported for "zpool" to catch it. | |
187 | [ -n "$ZPOOL_IMPORT_PATH" ] && export ZPOOL_IMPORT_PATH | |
188 | ||
189 | # Mount all availible pools (except those set in ZFS_POOL_EXCEPTIONS. | |
190 | # | |
191 | # If not interactive (run from init - variable init='/sbin/init') | |
192 | # we get ONE line for all pools being imported, with just a dot | |
193 | # as status for each pool. | |
194 | # Example: Importing ZFS pool(s)... [OK] | |
195 | # | |
196 | # If it IS interactive (started from the shell manually), then we | |
197 | # get one line per pool importing. | |
198 | # Example: Importing ZFS pool pool1 [OK] | |
199 | # Importing ZFS pool pool2 [OK] | |
200 | # [etc] | |
201 | [ -n "$init" ] && zfs_log_begin_msg "Importing ZFS pool(s)" | |
202 | OLD_IFS="$IFS" ; IFS=";" | |
203 | for pool in $available_pools | |
204 | do | |
205 | [ -z "$pool" ] && continue | |
206 | ||
207 | # We have pools that haven't been imported - import them | |
208 | if [ -n "$init" ] | |
209 | then | |
210 | # Not interactive - a dot for each pool. | |
211 | # Except on Gentoo where this doesn't work. | |
212 | zfs_log_progress_msg "." | |
213 | else | |
214 | # Interactive - one 'Importing ...' line per pool | |
215 | zfs_log_begin_msg "Importing ZFS pool $pool" | |
216 | fi | |
217 | ||
218 | # Import by using ZPOOL_IMPORT_PATH (either set above or in | |
219 | # the config file) _or_ with the 'built in' default search | |
cae5b340 | 220 | # paths. This is the preferred way. |
e10b0808 AX |
221 | "$ZPOOL" import -N ${ZPOOL_IMPORT_OPTS} "$pool" 2> /dev/null |
222 | r="$?" ; RET=$((RET + r)) | |
223 | if [ "$r" -eq 0 ] | |
224 | then | |
225 | # Output success and process the next pool | |
226 | [ -z "$init" ] && zfs_log_end_msg 0 | |
227 | continue | |
228 | fi | |
229 | # We don't want a fail msg here, we're going to try import | |
230 | # using the cache file soon and that might succeed. | |
231 | [ ! -f "$ZPOOL_CACHE" ] && zfs_log_end_msg "$RET" | |
232 | ||
233 | if [ "$r" -gt 0 -a -f "$ZPOOL_CACHE" ] | |
234 | then | |
235 | # Failed to import without a cache file. Try WITH... | |
236 | if [ -z "$init" ] && check_boolean "$VERBOSE_MOUNT" | |
237 | then | |
238 | # Interactive + Verbose = more information | |
239 | zfs_log_progress_msg " using cache file" | |
240 | fi | |
241 | ||
242 | "$ZPOOL" import -c "$ZPOOL_CACHE" -N ${ZPOOL_IMPORT_OPTS} \ | |
243 | "$pool" 2> /dev/null | |
244 | r="$?" ; RET=$((RET + r)) | |
245 | if [ "$r" -eq 0 ] | |
246 | then | |
247 | [ -z "$init" ] && zfs_log_end_msg 0 | |
248 | continue 3 # Next pool | |
249 | fi | |
250 | zfs_log_end_msg "$RET" | |
251 | fi | |
252 | done | |
253 | [ -n "$init" ] && zfs_log_end_msg "$RET" | |
254 | ||
255 | IFS="$OLD_IFS" | |
256 | [ -n "$already_imported" -a -z "$available_pools" ] && return 0 | |
257 | ||
258 | return "$RET" | |
259 | } | |
260 | ||
261 | do_import() | |
262 | { | |
263 | if check_boolean "$ZPOOL_IMPORT_ALL_VISIBLE" | |
264 | then | |
265 | do_import_all_visible | |
266 | else | |
267 | # This is the default option | |
268 | do_verbatim_import | |
269 | fi | |
270 | } | |
271 | ||
272 | # Output the status and list of pools | |
273 | do_status() | |
274 | { | |
275 | check_module_loaded "zfs" || exit 0 | |
276 | ||
277 | "$ZPOOL" status && echo "" && "$ZPOOL" list | |
278 | } | |
279 | ||
280 | do_start() | |
281 | { | |
282 | if check_boolean "$VERBOSE_MOUNT" | |
283 | then | |
284 | zfs_log_begin_msg "Checking if ZFS userspace tools present" | |
285 | fi | |
286 | ||
287 | if checksystem | |
288 | then | |
289 | check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0 | |
290 | ||
291 | check_boolean "$VERBOSE_MOUNT" && \ | |
292 | zfs_log_begin_msg "Loading kernel ZFS infrastructure" | |
293 | ||
294 | if ! load_module "zfs" | |
295 | then | |
296 | check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 1 | |
297 | return 5 | |
298 | fi | |
299 | check_boolean "$VERBOSE_MOUNT" && zfs_log_end_msg 0 | |
300 | ||
301 | do_import && udev_trigger # just to make sure we get zvols. | |
302 | ||
303 | return 0 | |
304 | else | |
305 | return 1 | |
306 | fi | |
307 | } | |
308 | ||
309 | # ---------------------------------------------------- | |
310 | ||
cae5b340 | 311 | if [ ! -e /sbin/openrc-run ] |
e10b0808 AX |
312 | then |
313 | case "$1" in | |
314 | start) | |
315 | do_start | |
316 | ;; | |
317 | stop) | |
318 | # no-op | |
319 | ;; | |
320 | status) | |
321 | do_status | |
322 | ;; | |
323 | force-reload|condrestart|reload|restart) | |
324 | # no-op | |
325 | ;; | |
326 | *) | |
327 | [ -n "$1" ] && echo "Error: Unknown command $1." | |
328 | echo "Usage: $0 {start|status}" | |
329 | exit 3 | |
330 | ;; | |
331 | esac | |
332 | ||
333 | exit $? | |
334 | else | |
335 | # Create wrapper functions since Gentoo don't use the case part. | |
336 | depend() { do_depend; } | |
337 | start() { do_start; } | |
338 | status() { do_status; } | |
339 | fi |