mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-28 03:49:38 +03:00
16421a1dc8
* In read_mtab(), fix problems (!?) in the mounts file. It will record 'rpool 1' as 'rpool\0401' instead of 'rpool\00401' which seems to be the correct (at least as far as 'printf' is concerned). Use this using the external 'echo' command (and not the one built in to the shell) because the internal one would interpret the backslash code (incorrectly), giving us a instead. * Remove reregister_mounts() - no longer needed. * For Gentoo, the zfs_log_failure_msg() should use eend(), not eerror() (which requires an error message, which we don't have). Signed-off-by: Turbo Fredriksson <turbo@bayour.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #3488 Closes #3509 Closes #3514
417 lines
9.1 KiB
Plaintext
417 lines
9.1 KiB
Plaintext
# This is a script with common functions etc used by zfs-import, zfs-mount,
|
||
# zfs-share and zfs-zed.
|
||
#
|
||
# It is _NOT_ to be called independently
|
||
#
|
||
# Released under the 2-clause BSD license.
|
||
#
|
||
# The original script that acted as a template for this script came from
|
||
# the Debian GNU/Linux kFreeBSD ZFS packages (which did not include a
|
||
# licensing stansa) in the commit dated Mar 24, 2011:
|
||
# https://github.com/zfsonlinux/pkg-zfs/commit/80a3ae582b59c0250d7912ba794dca9e669e605a
|
||
|
||
PATH=/sbin:/bin:/usr/bin:/usr/sbin
|
||
|
||
# Source function library
|
||
if [ -f /etc/rc.d/init.d/functions ]; then
|
||
# RedHat and derivates
|
||
. /etc/rc.d/init.d/functions
|
||
elif [ -L /etc/init.d/functions.sh ]; then
|
||
# Gentoo
|
||
. /etc/init.d/functions.sh
|
||
elif [ -f /lib/lsb/init-functions ]; then
|
||
# LSB, Debian GNU/Linux and derivates
|
||
. /lib/lsb/init-functions
|
||
fi
|
||
|
||
# Of course the functions we need are called differently
|
||
# on different distributions - it would be way too easy
|
||
# otherwise!!
|
||
if type log_failure_msg > /dev/null 2>&1 ; then
|
||
# LSB functions - fall through
|
||
zfs_log_begin_msg() { log_begin_msg "$1"; }
|
||
zfs_log_end_msg() { log_end_msg "$1"; }
|
||
zfs_log_failure_msg() { log_failure_msg "$1"; }
|
||
zfs_log_progress_msg() { log_progress_msg "$1"; }
|
||
elif type success > /dev/null 2>&1 ; then
|
||
# Fedora/RedHat functions
|
||
zfs_set_ifs() {
|
||
# For some reason, the init function library have a problem
|
||
# with a changed IFS, so this function goes around that.
|
||
local tIFS="$1"
|
||
if [ -n "$tIFS" ]
|
||
then
|
||
TMP_IFS="$IFS"
|
||
IFS="$tIFS"
|
||
fi
|
||
}
|
||
|
||
zfs_log_begin_msg() { echo -n "$1 "; }
|
||
zfs_log_end_msg() {
|
||
zfs_set_ifs "$OLD_IFS"
|
||
if [ "$1" -eq 0 ]; then
|
||
success
|
||
else
|
||
failure
|
||
fi
|
||
echo
|
||
zfs_set_ifs "$TMP_IFS"
|
||
}
|
||
zfs_log_failure_msg() {
|
||
zfs_set_ifs "$OLD_IFS"
|
||
failure
|
||
echo
|
||
zfs_set_ifs "$TMP_IFS"
|
||
}
|
||
zfs_log_progress_msg() { echo -n $"$1"; }
|
||
elif type einfo > /dev/null 2>&1 ; then
|
||
# Gentoo functions
|
||
zfs_log_begin_msg() { ebegin "$1"; }
|
||
zfs_log_end_msg() { eend "$1"; }
|
||
zfs_log_failure_msg() { eend "$1"; }
|
||
# zfs_log_progress_msg() { echo -n "$1"; }
|
||
zfs_log_progress_msg() { echo -n; }
|
||
else
|
||
# Unknown - simple substitues.
|
||
zfs_log_begin_msg() { echo -n "$1"; }
|
||
zfs_log_end_msg() {
|
||
ret=$1
|
||
if [ "$ret" -ge 1 ]; then
|
||
echo " failed!"
|
||
else
|
||
echo " success"
|
||
fi
|
||
return "$ret"
|
||
}
|
||
zfs_log_failure_msg() { echo "$1"; }
|
||
zfs_log_progress_msg() { echo -n "$1"; }
|
||
fi
|
||
|
||
# Paths to what we need
|
||
ZFS="@sbindir@/zfs"
|
||
ZED="@sbindir@/zed"
|
||
ZPOOL="@sbindir@/zpool"
|
||
ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache"
|
||
|
||
# Sensible defaults
|
||
ZFS_MOUNT='yes'
|
||
ZFS_UNMOUNT='yes'
|
||
|
||
export ZFS ZED ZPOOL ZPOOL_CACHE ZFS_MOUNT ZFS_UNMOUNT
|
||
|
||
# Source zfs configuration, overriding the defaults
|
||
if [ -f @initconfdir@/zfs ]; then
|
||
. @initconfdir@/zfs
|
||
fi
|
||
|
||
# ----------------------------------------------------
|
||
|
||
zfs_action()
|
||
{
|
||
local MSG="$1"; shift
|
||
local CMD="$*"
|
||
local ret
|
||
|
||
zfs_log_begin_msg "$MSG "
|
||
$CMD
|
||
ret=$?
|
||
if [ "$ret" -eq 0 ]; then
|
||
zfs_log_end_msg $ret
|
||
else
|
||
zfs_log_failure_msg $ret
|
||
fi
|
||
|
||
return $ret
|
||
}
|
||
|
||
# Returns
|
||
# 0 if daemon has been started
|
||
# 1 if daemon was already running
|
||
# 2 if daemon could not be started
|
||
# 3 if unsupported
|
||
#
|
||
zfs_daemon_start()
|
||
{
|
||
local PIDFILE="$1"; shift
|
||
local DAEMON_BIN="$1"; shift
|
||
local DAEMON_ARGS="$*"
|
||
|
||
if type start-stop-daemon > /dev/null 2>&1 ; then
|
||
# LSB functions
|
||
start-stop-daemon --start --quiet --pidfile "$PIDFILE" \
|
||
--exec "$DAEMON_BIN" --test > /dev/null || return 1
|
||
|
||
start-stop-daemon --start --quiet --exec "$DAEMON_BIN" -- \
|
||
$DAEMON_ARGS || return 2
|
||
|
||
# On Debian GNU/Linux, there's a 'sendsigs' script that will
|
||
# kill basically everything quite early and zed is stopped
|
||
# much later than that. We don't want zed to be among them,
|
||
# so add the zed pid to list of pids to ignore.
|
||
if [ -f "$PIDFILE" -a -d /run/sendsigs.omit.d ]
|
||
then
|
||
ln -s "$PIDFILE" /run/sendsigs.omit.d/zed
|
||
fi
|
||
elif type daemon > /dev/null 2>&1 ; then
|
||
# Fedora/RedHat functions
|
||
daemon --pidfile "$PIDFILE" "$DAEMON_BIN" $DAEMON_ARGS
|
||
return $?
|
||
else
|
||
# Unsupported
|
||
return 3
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# Returns
|
||
# 0 if daemon has been stopped
|
||
# 1 if daemon was already stopped
|
||
# 2 if daemon could not be stopped
|
||
# 3 if unsupported
|
||
#
|
||
zfs_daemon_stop()
|
||
{
|
||
local PIDFILE="$1"
|
||
local DAEMON_BIN="$2"
|
||
local DAEMON_NAME="$3"
|
||
|
||
if type start-stop-daemon > /dev/null 2>&1 ; then
|
||
# LSB functions
|
||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
|
||
--pidfile "$PIDFILE" --name "$DAEMON_NAME"
|
||
[ "$?" = 0 ] && rm -f "$PIDFILE"
|
||
|
||
return $?
|
||
elif type killproc > /dev/null 2>&1 ; then
|
||
# Fedora/RedHat functions
|
||
killproc -p "$PIDFILE" "$DAEMON_NAME"
|
||
[ "$?" = 0 ] && rm -f "$PIDFILE"
|
||
|
||
return $?
|
||
else
|
||
# Unsupported
|
||
return 3
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# Returns status
|
||
zfs_daemon_status()
|
||
{
|
||
local PIDFILE="$1"
|
||
local DAEMON_BIN="$2"
|
||
local DAEMON_NAME="$3"
|
||
|
||
if type status_of_proc > /dev/null 2>&1 ; then
|
||
# LSB functions
|
||
status_of_proc "$DAEMON_NAME" "$DAEMON_BIN"
|
||
return $?
|
||
elif type status > /dev/null 2>&1 ; then
|
||
# Fedora/RedHat functions
|
||
status -p "$PIDFILE" "$DAEMON_NAME"
|
||
return $?
|
||
else
|
||
# Unsupported
|
||
return 3
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
zfs_daemon_reload()
|
||
{
|
||
local PIDFILE="$1"
|
||
local DAEMON_NAME="$2"
|
||
|
||
if type start-stop-daemon > /dev/null 2>&1 ; then
|
||
# LSB functions
|
||
start-stop-daemon --stop -signal 1 --quiet \
|
||
--pidfile "$PIDFILE" --name "$DAEMON_NAME"
|
||
return $?
|
||
elif type killproc > /dev/null 2>&1 ; then
|
||
# Fedora/RedHat functions
|
||
killproc -p "$PIDFILE" "$DAEMON_NAME" -HUP
|
||
return $?
|
||
else
|
||
# Unsupported
|
||
return 3
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
zfs_installed()
|
||
{
|
||
if [ ! -x "$ZPOOL" ]; then
|
||
return 1
|
||
else
|
||
# Test if it works (will catch missing/broken libs etc)
|
||
"$ZPOOL" -? > /dev/null 2>&1
|
||
return $?
|
||
fi
|
||
|
||
if [ ! -x "$ZFS" ]; then
|
||
return 2
|
||
else
|
||
# Test if it works (will catch missing/broken libs etc)
|
||
"$ZFS" -? > /dev/null 2>&1
|
||
return $?
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# Trigger udev and wait for it to settle.
|
||
udev_trigger()
|
||
{
|
||
if [ -x /sbin/udevadm ]; then
|
||
/sbin/udevadm trigger --action=change --subsystem-match=block
|
||
/sbin/udevadm settle
|
||
elif [ -x /sbin/udevsettle ]; then
|
||
/sbin/udevtrigger
|
||
/sbin/udevsettle
|
||
fi
|
||
}
|
||
|
||
# Do a lot of checks to make sure it's 'safe' to continue with the import.
|
||
checksystem()
|
||
{
|
||
if grep -qiE '(^|[^\\](\\\\)* )zfs=(off|no|0)( |$)' /proc/cmdline;
|
||
then
|
||
# Called with zfs=(off|no|0) - bail because we don't
|
||
# want anything import, mounted or shared.
|
||
# HOWEVER, only do this if we're called at the boot up
|
||
# (from init), not if we're running interactivly (as in
|
||
# from the shell - we know what we're doing).
|
||
[ -n "$init" ] && exit 3
|
||
fi
|
||
|
||
# Check if ZFS is installed.
|
||
zfs_installed || return 5
|
||
|
||
# Just make sure that /dev/zfs is created.
|
||
udev_trigger
|
||
|
||
if ! [ "$(uname -m)" = "x86_64" ]; then
|
||
echo "Warning: You're not running 64bit. Currently native zfs in";
|
||
echo " Linux is only supported and tested on 64bit.";
|
||
# should we break here? People doing this should know what they
|
||
# do, thus i'm not breaking here.
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
get_root_pool()
|
||
{
|
||
set -- $(mount | grep ' on / ')
|
||
[ "$5" = "zfs" ] && echo "${1%%/*}"
|
||
}
|
||
|
||
check_module_loaded()
|
||
{
|
||
[ -r /sys/module/zfs/version ] && return 0 || return 1
|
||
}
|
||
|
||
load_module()
|
||
{
|
||
# Load the zfs module stack
|
||
if ! check_module_loaded; then
|
||
if ! modprobe zfs; then
|
||
return 5
|
||
fi
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
# first parameter is a regular expression that filters mtab
|
||
read_mtab()
|
||
{
|
||
local match="$1"
|
||
local fs mntpnt fstype opts rest TMPFILE
|
||
|
||
# Unset all MTAB_* variables
|
||
unset $(env | grep ^MTAB_ | sed 's,=.*,,')
|
||
|
||
while read -r fs mntpnt fstype opts rest; do
|
||
if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then
|
||
# * Fix problems (!?) in the mounts file. It will record
|
||
# 'rpool 1' as 'rpool\0401' instead of 'rpool\00401'
|
||
# which seems to be the correct (at least as far as
|
||
# 'printf' is concerned).
|
||
# * We need to use the external echo, because the
|
||
# internal one would interpret the backslash code
|
||
# (incorrectly), giving us a instead.
|
||
mntpnt=$(/bin/echo "$mntpnt" | sed "s,\\\0,\\\00,")
|
||
fs=$(/bin/echo "$fs" | sed "s,\\\0,\\\00,")
|
||
|
||
# Replace 'unwanted' characters with underscore.
|
||
mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,_,g' \
|
||
-e 's,-,_,g' -e 's,\.,_,g' -e 's, ,_,g')
|
||
fs=$(printf '%b\n' "$fs")
|
||
|
||
# Set the variable.
|
||
eval export MTAB_$mntpnt=\"$fs\"
|
||
fi
|
||
done < /proc/mounts
|
||
}
|
||
|
||
in_mtab()
|
||
{
|
||
local fs="$(echo "$1" | sed 's,/,_,g')"
|
||
local var
|
||
|
||
var="$(eval echo MTAB_$fs)"
|
||
[ "$(eval echo "$""$var")" != "" ]
|
||
return "$?"
|
||
}
|
||
|
||
# first parameter is a regular expression that filters fstab
|
||
read_fstab()
|
||
{
|
||
local match="$1"
|
||
local i var TMPFILE
|
||
|
||
# Unset all FSTAB_* variables
|
||
unset $(env | grep ^FSTAB_ | sed 's,=.*,,')
|
||
|
||
i=0
|
||
while read -r fs mntpnt fstype opts; do
|
||
echo "$fs" | egrep -qE '^#|^$' && continue
|
||
|
||
if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then
|
||
eval export FSTAB_dev_$i="$fs"
|
||
fs=$(printf '%b\n' "$fs" | sed 's,/,_,g')
|
||
eval export FSTAB_$i="$mntpnt"
|
||
|
||
i=$((i + 1))
|
||
fi
|
||
done < /etc/fstab
|
||
}
|
||
|
||
in_fstab()
|
||
{
|
||
local var
|
||
|
||
var="$(eval echo FSTAB_$1)"
|
||
[ "${var}" != "" ]
|
||
return $?
|
||
}
|
||
|
||
is_mounted()
|
||
{
|
||
local mntpt="$1"
|
||
local line
|
||
|
||
mount | \
|
||
while read line; do
|
||
if echo "$line" | grep -q " on $mntpt "; then
|
||
return 0
|
||
fi
|
||
done
|
||
|
||
return 1
|
||
}
|