]> git.proxmox.com Git - mirror_zfs.git/blame - etc/init.d/zfs-functions.in
zfs filesystem skipped by df -h
[mirror_zfs.git] / etc / init.d / zfs-functions.in
CommitLineData
2a34db1b
TF
1# This is a script with common functions etc used by zfs-import, zfs-mount,
2# zfs-share and zfs-zed.
3#
4# It is _NOT_ to be called independently
5#
6# Released under the 2-clause BSD license.
7#
8# The original script that acted as a template for this script came from
9# the Debian GNU/Linux kFreeBSD ZFS packages (which did not include a
10# licensing stansa) in the commit dated Mar 24, 2011:
11# https://github.com/zfsonlinux/pkg-zfs/commit/80a3ae582b59c0250d7912ba794dca9e669e605a
12
13PATH=/sbin:/bin:/usr/bin:/usr/sbin
14
15# Source function library
4f38c259 16if [ -f /etc/rc.d/init.d/functions ]; then
2a34db1b
TF
17 # RedHat and derivates
18 . /etc/rc.d/init.d/functions
19elif [ -L /etc/init.d/functions.sh ]; then
20 # Gentoo
21 . /etc/init.d/functions.sh
4f38c259
TF
22elif [ -f /lib/lsb/init-functions ]; then
23 # LSB, Debian GNU/Linux and derivates
24 . /lib/lsb/init-functions
2a34db1b
TF
25fi
26
27# Of course the functions we need are called differently
28# on different distributions - it would be way too easy
29# otherwise!!
30if type log_failure_msg > /dev/null 2>&1 ; then
31 # LSB functions - fall through
32 zfs_log_begin_msg() { log_begin_msg "$1"; }
33 zfs_log_end_msg() { log_end_msg "$1"; }
34 zfs_log_failure_msg() { log_failure_msg "$1"; }
35 zfs_log_progress_msg() { log_progress_msg "$1"; }
36elif type success > /dev/null 2>&1 ; then
37 # Fedora/RedHat functions
38 zfs_set_ifs() {
39 # For some reason, the init function library have a problem
40 # with a changed IFS, so this function goes around that.
41 local tIFS="$1"
42 if [ -n "$tIFS" ]
43 then
44 TMP_IFS="$IFS"
45 IFS="$tIFS"
46 fi
47 }
48
49 zfs_log_begin_msg() { echo -n "$1 "; }
50 zfs_log_end_msg() {
51 zfs_set_ifs "$OLD_IFS"
52 if [ "$1" -eq 0 ]; then
53 success
54 else
55 failure
56 fi
57 echo
58 zfs_set_ifs "$TMP_IFS"
59 }
60 zfs_log_failure_msg() {
61 zfs_set_ifs "$OLD_IFS"
62 failure
63 echo
64 zfs_set_ifs "$TMP_IFS"
65 }
66 zfs_log_progress_msg() { echo -n $"$1"; }
67elif type einfo > /dev/null 2>&1 ; then
68 # Gentoo functions
69 zfs_log_begin_msg() { ebegin "$1"; }
70 zfs_log_end_msg() { eend "$1"; }
16421a1d 71 zfs_log_failure_msg() { eend "$1"; }
2a34db1b
TF
72# zfs_log_progress_msg() { echo -n "$1"; }
73 zfs_log_progress_msg() { echo -n; }
74else
75 # Unknown - simple substitues.
76 zfs_log_begin_msg() { echo -n "$1"; }
77 zfs_log_end_msg() {
78 ret=$1
79 if [ "$ret" -ge 1 ]; then
80 echo " failed!"
81 else
82 echo " success"
83 fi
84 return "$ret"
85 }
86 zfs_log_failure_msg() { echo "$1"; }
87 zfs_log_progress_msg() { echo -n "$1"; }
88fi
89
90# Paths to what we need
91ZFS="@sbindir@/zfs"
92ZED="@sbindir@/zed"
93ZPOOL="@sbindir@/zpool"
94ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache"
95
96# Sensible defaults
97ZFS_MOUNT='yes'
98ZFS_UNMOUNT='yes'
99
100export ZFS ZED ZPOOL ZPOOL_CACHE ZFS_MOUNT ZFS_UNMOUNT
101
102# Source zfs configuration, overriding the defaults
103if [ -f @initconfdir@/zfs ]; then
104 . @initconfdir@/zfs
105fi
106
107# ----------------------------------------------------
108
109zfs_action()
110{
111 local MSG="$1"; shift
112 local CMD="$*"
113 local ret
114
115 zfs_log_begin_msg "$MSG "
116 $CMD
117 ret=$?
118 if [ "$ret" -eq 0 ]; then
119 zfs_log_end_msg $ret
120 else
121 zfs_log_failure_msg $ret
122 fi
123
124 return $ret
125}
126
127# Returns
128# 0 if daemon has been started
129# 1 if daemon was already running
130# 2 if daemon could not be started
131# 3 if unsupported
132#
133zfs_daemon_start()
134{
135 local PIDFILE="$1"; shift
136 local DAEMON_BIN="$1"; shift
137 local DAEMON_ARGS="$*"
138
139 if type start-stop-daemon > /dev/null 2>&1 ; then
140 # LSB functions
141 start-stop-daemon --start --quiet --pidfile "$PIDFILE" \
142 --exec "$DAEMON_BIN" --test > /dev/null || return 1
143
144 start-stop-daemon --start --quiet --exec "$DAEMON_BIN" -- \
145 $DAEMON_ARGS || return 2
146
147 # On Debian GNU/Linux, there's a 'sendsigs' script that will
148 # kill basically everything quite early and zed is stopped
149 # much later than that. We don't want zed to be among them,
150 # so add the zed pid to list of pids to ignore.
151 if [ -f "$PIDFILE" -a -d /run/sendsigs.omit.d ]
152 then
1e17e910 153 ln -sf "$PIDFILE" /run/sendsigs.omit.d/zed
2a34db1b
TF
154 fi
155 elif type daemon > /dev/null 2>&1 ; then
156 # Fedora/RedHat functions
157 daemon --pidfile "$PIDFILE" "$DAEMON_BIN" $DAEMON_ARGS
158 return $?
159 else
160 # Unsupported
161 return 3
162 fi
163
164 return 0
165}
166
167# Returns
168# 0 if daemon has been stopped
169# 1 if daemon was already stopped
170# 2 if daemon could not be stopped
171# 3 if unsupported
172#
173zfs_daemon_stop()
174{
175 local PIDFILE="$1"
176 local DAEMON_BIN="$2"
177 local DAEMON_NAME="$3"
178
179 if type start-stop-daemon > /dev/null 2>&1 ; then
180 # LSB functions
181 start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
182 --pidfile "$PIDFILE" --name "$DAEMON_NAME"
183 [ "$?" = 0 ] && rm -f "$PIDFILE"
184
185 return $?
186 elif type killproc > /dev/null 2>&1 ; then
187 # Fedora/RedHat functions
188 killproc -p "$PIDFILE" "$DAEMON_NAME"
189 [ "$?" = 0 ] && rm -f "$PIDFILE"
190
191 return $?
192 else
193 # Unsupported
194 return 3
195 fi
196
197 return 0
198}
199
200# Returns status
201zfs_daemon_status()
202{
203 local PIDFILE="$1"
204 local DAEMON_BIN="$2"
205 local DAEMON_NAME="$3"
206
207 if type status_of_proc > /dev/null 2>&1 ; then
208 # LSB functions
209 status_of_proc "$DAEMON_NAME" "$DAEMON_BIN"
210 return $?
211 elif type status > /dev/null 2>&1 ; then
212 # Fedora/RedHat functions
213 status -p "$PIDFILE" "$DAEMON_NAME"
214 return $?
215 else
216 # Unsupported
217 return 3
218 fi
219
220 return 0
221}
222
223zfs_daemon_reload()
224{
225 local PIDFILE="$1"
226 local DAEMON_NAME="$2"
227
228 if type start-stop-daemon > /dev/null 2>&1 ; then
229 # LSB functions
4a4809fa 230 start-stop-daemon --stop --signal 1 --quiet \
2a34db1b
TF
231 --pidfile "$PIDFILE" --name "$DAEMON_NAME"
232 return $?
233 elif type killproc > /dev/null 2>&1 ; then
234 # Fedora/RedHat functions
235 killproc -p "$PIDFILE" "$DAEMON_NAME" -HUP
236 return $?
237 else
238 # Unsupported
239 return 3
240 fi
241
242 return 0
243}
244
245zfs_installed()
246{
247 if [ ! -x "$ZPOOL" ]; then
248 return 1
249 else
250 # Test if it works (will catch missing/broken libs etc)
251 "$ZPOOL" -? > /dev/null 2>&1
252 return $?
253 fi
254
255 if [ ! -x "$ZFS" ]; then
256 return 2
257 else
258 # Test if it works (will catch missing/broken libs etc)
259 "$ZFS" -? > /dev/null 2>&1
260 return $?
261 fi
262
263 return 0
264}
265
266# Trigger udev and wait for it to settle.
267udev_trigger()
268{
269 if [ -x /sbin/udevadm ]; then
270 /sbin/udevadm trigger --action=change --subsystem-match=block
271 /sbin/udevadm settle
272 elif [ -x /sbin/udevsettle ]; then
273 /sbin/udevtrigger
274 /sbin/udevsettle
275 fi
276}
277
278# Do a lot of checks to make sure it's 'safe' to continue with the import.
279checksystem()
280{
281 if grep -qiE '(^|[^\\](\\\\)* )zfs=(off|no|0)( |$)' /proc/cmdline;
282 then
283 # Called with zfs=(off|no|0) - bail because we don't
284 # want anything import, mounted or shared.
285 # HOWEVER, only do this if we're called at the boot up
286 # (from init), not if we're running interactivly (as in
287 # from the shell - we know what we're doing).
288 [ -n "$init" ] && exit 3
289 fi
290
291 # Check if ZFS is installed.
292 zfs_installed || return 5
293
294 # Just make sure that /dev/zfs is created.
295 udev_trigger
296
297 if ! [ "$(uname -m)" = "x86_64" ]; then
298 echo "Warning: You're not running 64bit. Currently native zfs in";
299 echo " Linux is only supported and tested on 64bit.";
300 # should we break here? People doing this should know what they
301 # do, thus i'm not breaking here.
302 fi
303
304 return 0
305}
306
2a34db1b
TF
307get_root_pool()
308{
309 set -- $(mount | grep ' on / ')
310 [ "$5" = "zfs" ] && echo "${1%%/*}"
311}
312
57732964
TF
313# Check if a variable is 'yes' (any case) or '1'
314# Returns TRUE if set.
315check_boolean()
316{
317 local var="$1"
318
319 echo "$var" | grep -Eiq "^yes$|^on$|^true$|^1$" && return 0 || return 1
320}
321
2a34db1b
TF
322check_module_loaded()
323{
48511ea6
TF
324 module="$1"
325
326 [ -r "/sys/module/${module}/version" ] && return 0 || return 1
2a34db1b
TF
327}
328
329load_module()
330{
48511ea6
TF
331 module="$1"
332
2a34db1b 333 # Load the zfs module stack
48511ea6
TF
334 if ! check_module_loaded "$module"; then
335 if ! /sbin/modprobe "$module"; then
2a34db1b
TF
336 return 5
337 fi
338 fi
339 return 0
340}
341
342# first parameter is a regular expression that filters mtab
343read_mtab()
344{
345 local match="$1"
346 local fs mntpnt fstype opts rest TMPFILE
347
348 # Unset all MTAB_* variables
349 unset $(env | grep ^MTAB_ | sed 's,=.*,,')
350
216f9d04
TF
351 while read -r fs mntpnt fstype opts rest; do
352 if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then
16421a1d
TF
353 # * Fix problems (!?) in the mounts file. It will record
354 # 'rpool 1' as 'rpool\0401' instead of 'rpool\00401'
355 # which seems to be the correct (at least as far as
356 # 'printf' is concerned).
357 # * We need to use the external echo, because the
358 # internal one would interpret the backslash code
359 # (incorrectly), giving us a \ 1 instead.
57732964 360 mntpnt=$(/bin/echo "$mntpnt" | sed "s,\\\0,\\\00,g")
16421a1d
TF
361 fs=$(/bin/echo "$fs" | sed "s,\\\0,\\\00,")
362
57732964
TF
363 # Remove 'unwanted' characters.
364 mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,,g' \
365 -e 's,-,,g' -e 's,\.,,g' -e 's, ,,g')
16421a1d
TF
366 fs=$(printf '%b\n' "$fs")
367
368 # Set the variable.
369 eval export MTAB_$mntpnt=\"$fs\"
216f9d04 370 fi
79251738 371 done < /proc/self/mounts
2a34db1b
TF
372}
373
374in_mtab()
375{
376 local fs="$(echo "$1" | sed 's,/,_,g')"
377 local var
378
379 var="$(eval echo MTAB_$fs)"
380 [ "$(eval echo "$""$var")" != "" ]
381 return "$?"
382}
383
384# first parameter is a regular expression that filters fstab
385read_fstab()
386{
387 local match="$1"
388 local i var TMPFILE
389
390 # Unset all FSTAB_* variables
391 unset $(env | grep ^FSTAB_ | sed 's,=.*,,')
392
393 i=0
394 while read -r fs mntpnt fstype opts; do
395 echo "$fs" | egrep -qE '^#|^$' && continue
2f291eba
GY
396 echo "$mntpnt" | egrep -qE '^none|^swap' && continue
397 echo "$fstype" | egrep -qE '^swap' && continue
2a34db1b
TF
398
399 if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then
400 eval export FSTAB_dev_$i="$fs"
401 fs=$(printf '%b\n' "$fs" | sed 's,/,_,g')
402 eval export FSTAB_$i="$mntpnt"
403
404 i=$((i + 1))
405 fi
406 done < /etc/fstab
407}
408
409in_fstab()
410{
411 local var
412
413 var="$(eval echo FSTAB_$1)"
414 [ "${var}" != "" ]
415 return $?
416}
417
418is_mounted()
419{
420 local mntpt="$1"
421 local line
422
423 mount | \
424 while read line; do
425 if echo "$line" | grep -q " on $mntpt "; then
a0cc3726
T
426 # returns:
427 # 0 on unsuccessful match
428 # 1 on a successful match
429 return 1
2a34db1b
TF
430 fi
431 done
432
a0cc3726
T
433 # The negation will flip the subshell return result where the default
434 # return value is 0 when a match is not found.
435 return $(( !$? ))
2a34db1b 436}