mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-18 02:20:59 +03:00
216f9d04a6
This reverts commit 036391c980
.
Because #3509 came just after this commit was accepted and is related
to the original problem the commit was supposed to fix, we need to
solve the problem in another way.
Signed-off-by: Turbo Fredriksson <turbo@bayour.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
439 lines
9.5 KiB
Plaintext
439 lines
9.5 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() { eerror "$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
|
|
}
|
|
|
|
reregister_mounts()
|
|
{
|
|
local fs mntpnt fstype opts rest tmpdir
|
|
tmpdir=removethismountpointhoweverpossible
|
|
|
|
while read -r fs mntpnt fstype opts rest ; do
|
|
fs=$(printf '%b\n' "$fs")
|
|
mntpnt=$(printf '%b\n' "$mntpnt")
|
|
if [ "$fstype" = "zfs" ] ; then
|
|
if [ "$mntpnt" = "/" ] ; then
|
|
mount -f -o zfsutil -t zfs --move / /$tmpdir
|
|
umount --fake /$tmpdir
|
|
else
|
|
umount --fake "$mntpnt"
|
|
fi
|
|
elif echo "$fs" | grep -qE "^/dev/(zd|zvol)" ; then
|
|
if [ "$mntpnt" = "/" ] ; then
|
|
mount -f -t "$fstype" --move / /$tmpdir
|
|
umount --fake /$tmpdir
|
|
else
|
|
umount --fake "$mntpnt"
|
|
fi
|
|
fi
|
|
done < /proc/mounts
|
|
|
|
while read -r fs mntpnt fstype opts rest ; do
|
|
fs=$(printf '%b\n' "$fs")
|
|
mntpnt=$(printf '%b\n' "$mntpnt")
|
|
if [ "$fstype" = "zfs" ] ; then
|
|
mount -f -t zfs -o zfsutil "$fs" "$mntpnt"
|
|
elif echo "$fs" | grep -q "^/dev/zd" ; then
|
|
mount -f -t "$fstype" -o "$opts" "$fs" "$mntpnt"
|
|
fi
|
|
done < /proc/mounts
|
|
}
|
|
|
|
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
|
|
mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,_,g' \
|
|
-e 's,-,_,g' -e 's,\.,_,g')
|
|
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
|
|
}
|