mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
337ef7c1b4
For example, in Sys-V init "rquotad" is started by the main "nfs" service. At the moment the call-out can't distinguish between this case and "should never be run". Services set to "AUTO" are hand-stopped/started via service_stop()/service_start() on failure via restart_after. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
438 lines
8.9 KiB
Bash
Executable File
438 lines
8.9 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Exit on 1st error
|
|
set -e
|
|
|
|
# NFS exports file. Some code below keeps a cache of output derived
|
|
# from exportfs(8). When this file is updated the cache is invalid
|
|
# and needs to be regenerated.
|
|
#
|
|
# To change the file, edit the default value below. Do not set
|
|
# CTDB_NFS_EXPORTS_FILE - it isn't a configuration variable, just a
|
|
# hook for testing.
|
|
nfs_exports_file="${CTDB_NFS_EXPORTS_FILE:-/var/lib/nfs/etab}"
|
|
|
|
# As above, edit the default value below. CTDB_NFS_DISTRO_STYLE is a
|
|
# test variable only.
|
|
nfs_distro_style="${CTDB_NFS_DISTRO_STYLE:-systemd-redhat}"
|
|
|
|
# A value of "AUTO" for any service means that service is usually
|
|
# automatically started and stopped by one of the other services.
|
|
# Such services will still be restarted by hand on failure, if
|
|
# configured to do so. This allows services that should not be
|
|
# running to be set to "".
|
|
|
|
case "$nfs_distro_style" in
|
|
systemd-*)
|
|
# Defaults
|
|
nfs_service="nfs-server"
|
|
nfs_lock_service="rpc-statd"
|
|
nfs_mountd_service="nfs-mountd"
|
|
nfs_status_service="rpc-statd"
|
|
nfs_rquotad_service="rpc-rquotad"
|
|
nfs_config="/etc/sysconfig/nfs"
|
|
nfs_rquotad_config="" # Not use with systemd, restart via service
|
|
|
|
case "$nfs_distro_style" in
|
|
*-redhat | *-suse)
|
|
: # Defaults only
|
|
;;
|
|
*-debian)
|
|
nfs_rquotad_service="quotarpc"
|
|
;;
|
|
*)
|
|
echo "Internal error"
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
|
|
sysvinit-*)
|
|
# Defaults
|
|
nfs_service="nfs"
|
|
nfs_lock_service="AUTO"
|
|
nfs_mountd_service="AUTO"
|
|
nfs_status_service="AUTO"
|
|
nfs_rquotad_service="AUTO"
|
|
nfs_config="/etc/sysconfig/nfs"
|
|
nfs_rquotad_config="$nfs_config"
|
|
|
|
case "$nfs_distro_style" in
|
|
*-redhat)
|
|
nfs_lock_service="nfslock"
|
|
;;
|
|
*-suse)
|
|
nfs_service="nfsserver"
|
|
;;
|
|
*-debian)
|
|
nfs_service="nfs-kernel-server"
|
|
nfs_config="/etc/default/nfs-kernel-server"
|
|
nfs_rquotad_config="/etc/default/quota"
|
|
;;
|
|
*)
|
|
echo "Internal error"
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
|
|
*)
|
|
echo "Internal error"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# Override for unit testing
|
|
if [ -z "$PROCFS_PATH" ]; then
|
|
PROCFS_PATH="/proc"
|
|
fi
|
|
|
|
##################################################
|
|
|
|
usage()
|
|
{
|
|
_c=$(basename "$0")
|
|
cat <<EOF
|
|
usage: $_c { shutdown | startup }
|
|
$_c { stop | start } { nfs | nlockmgr }
|
|
$_c { monitor-list-shares | monitor-post }
|
|
$_c { register }
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
##################################################
|
|
|
|
nfs_load_config()
|
|
{
|
|
_config="${1:-${nfs_config}}"
|
|
|
|
if [ -r "$_config" ]; then
|
|
. "$_config"
|
|
fi
|
|
}
|
|
|
|
##################################################
|
|
|
|
service_is_auto_started()
|
|
{
|
|
[ "$1" = "AUTO" ]
|
|
}
|
|
|
|
service_is_defined()
|
|
{
|
|
_service="$1"
|
|
|
|
[ -n "$_service" ] && ! service_is_auto_started "$_service"
|
|
}
|
|
|
|
service_if_defined()
|
|
{
|
|
_service="$1"
|
|
_action="$2"
|
|
|
|
if service_is_defined "$_service"; then
|
|
service "$_service" "$_action"
|
|
fi
|
|
}
|
|
|
|
##################################################
|
|
# Overall NFS service stop and start
|
|
|
|
nfs_service_stop()
|
|
{
|
|
service_if_defined "$nfs_rquotad_service" stop
|
|
|
|
service "$nfs_service" stop
|
|
|
|
service_if_defined "$nfs_lock_service" stop
|
|
}
|
|
|
|
nfs_service_start()
|
|
{
|
|
service_if_defined "$nfs_lock_service" start
|
|
|
|
service "$nfs_service" start
|
|
|
|
service_if_defined "$nfs_rquotad_service" start
|
|
}
|
|
|
|
##################################################
|
|
# service "stop" and "start" options for restarting
|
|
|
|
manual_stop()
|
|
{
|
|
case "$1" in
|
|
mountd)
|
|
killall -q -9 rpc.mountd
|
|
;;
|
|
rquotad)
|
|
killall -q -9 rpc.rquotad
|
|
;;
|
|
status)
|
|
killall -q -9 rpc.statd
|
|
;;
|
|
*)
|
|
echo "$0: Internal error - invalid call to manual_stop()"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
service_or_manual_stop()
|
|
{
|
|
_rpc_service="$1"
|
|
_system_service="$2"
|
|
|
|
if service_is_defined "$_system_service"; then
|
|
service "$_system_service" stop
|
|
elif service_is_auto_started "$_system_service"; then
|
|
manual_stop "$_rpc_service"
|
|
fi
|
|
}
|
|
|
|
service_stop()
|
|
{
|
|
_rpc_service="$1"
|
|
|
|
case "$_rpc_service" in
|
|
nfs)
|
|
echo 0 >"${PROCFS_PATH}/fs/nfsd/threads"
|
|
nfs_service_stop >/dev/null 2>&1 || true
|
|
pkill -9 nfsd
|
|
;;
|
|
nlockmgr)
|
|
if service_is_defined "$nfs_lock_service" ; then
|
|
service "$nfs_lock_service" stop >/dev/null 2>&1 || true
|
|
else
|
|
service "$nfs_service" stop >/dev/null 2>&1 || true
|
|
fi
|
|
;;
|
|
mountd)
|
|
service_or_manual_stop "$_rpc_service" "$nfs_mountd_service"
|
|
;;
|
|
rquotad)
|
|
service_or_manual_stop "$_rpc_service" "$nfs_rquotad_service"
|
|
;;
|
|
status)
|
|
service_or_manual_stop "$_rpc_service" "$nfs_status_service"
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
}
|
|
|
|
manual_start()
|
|
{
|
|
case "$1" in
|
|
mountd)
|
|
nfs_load_config
|
|
if [ -z "$RPCMOUNTDOPTS" ]; then
|
|
RPCMOUNTDOPTS="${MOUNTD_PORT:+-p }$MOUNTD_PORT"
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
rpc.mountd $RPCMOUNTDOPTS
|
|
;;
|
|
rquotad)
|
|
nfs_load_config "$nfs_rquotad_config"
|
|
if [ -z "$RPCRQUOTADOPTS" ]; then
|
|
RPCRQUOTADOPTS="${RQUOTAD_PORT:+-p }$RQUOTAD_PORT"
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
rpc.rquotad $RPCRQUOTADOPTS
|
|
;;
|
|
status)
|
|
nfs_load_config
|
|
# Red Hat uses STATDARG, Debian uses STATDOPTS
|
|
opts="${STATDARG:-${STATDOPTS:-''}}"
|
|
if [ -z "$opts" ]; then
|
|
# shellcheck disable=SC2086
|
|
set -- \
|
|
${STATD_HA_CALLOUT:+-H} $STATD_HA_CALLOUT \
|
|
${STATD_HOSTNAME:+-n} $STATD_HOSTNAME \
|
|
${STATD_PORT:+-p} $STATD_PORT \
|
|
${STATD_OUTGOING_PORT:+-o} $STATD_OUTGOING_PORT
|
|
opts="$*"
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
rpc.statd $opts
|
|
;;
|
|
*)
|
|
echo "$0: Internal error - invalid call to manual_start()"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
service_or_manual_start()
|
|
{
|
|
_rpc_service="$1"
|
|
_system_service="$2"
|
|
|
|
if service_is_defined "$_system_service"; then
|
|
service "$_system_service" start
|
|
elif service_is_auto_started "$_system_service"; then
|
|
manual_start "$_rpc_service"
|
|
fi
|
|
}
|
|
|
|
service_start()
|
|
{
|
|
_rpc_service="$1"
|
|
|
|
case "$_rpc_service" in
|
|
nfs)
|
|
nfs_service_start
|
|
;;
|
|
nlockmgr)
|
|
if service_is_defined "$nfs_lock_service" ; then
|
|
service "$nfs_lock_service" start
|
|
else
|
|
service "$nfs_service" start
|
|
fi
|
|
;;
|
|
mountd)
|
|
service_or_manual_start "$_rpc_service" "$nfs_mountd_service"
|
|
;;
|
|
rquotad)
|
|
service_or_manual_start "$_rpc_service" "$nfs_rquotad_service"
|
|
;;
|
|
status)
|
|
service_or_manual_start "$_rpc_service" "$nfs_status_service"
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
}
|
|
|
|
##################################################
|
|
# service init startup and final shutdown
|
|
|
|
nfs_shutdown()
|
|
{
|
|
nfs_service_stop
|
|
}
|
|
|
|
nfs_startup()
|
|
{
|
|
nfs_service_stop || true
|
|
nfs_service_start
|
|
_f="${PROCFS_PATH}/sys/net/ipv4/tcp_tw_recycle"
|
|
if [ -f "$_f" ]; then
|
|
echo 1 >"$_f"
|
|
fi
|
|
}
|
|
|
|
##################################################
|
|
# monitor-post support
|
|
|
|
nfs_check_thread_count()
|
|
{
|
|
# Load NFS configuration to get desired number of threads.
|
|
nfs_load_config
|
|
|
|
# If $RPCNFSDCOUNT/$USE_KERNEL_NFSD_NUMBER isn't set then we could
|
|
# guess the default from the initscript. However, let's just
|
|
# assume that those using the default don't care about the number
|
|
# of threads and that they have switched on this feature in error.
|
|
_configured_threads="${RPCNFSDCOUNT:-${USE_KERNEL_NFSD_NUMBER}}"
|
|
if [ -z "$_configured_threads" ] && type nfsconf >/dev/null 2>&1; then
|
|
_configured_threads=$(nfsconf --get nfsd threads) || true
|
|
fi
|
|
[ -n "$_configured_threads" ] || return 0
|
|
|
|
_threads_file="${PROCFS_PATH}/fs/nfsd/threads"
|
|
|
|
# nfsd should be running the configured number of threads. If
|
|
# there are a different number of threads then tell nfsd the
|
|
# correct number.
|
|
read _running_threads <"$_threads_file" || {
|
|
echo "WARNING: Reading \"${_threads_file}\" unexpectedly failed"
|
|
exit 0
|
|
}
|
|
|
|
# Intentionally not arithmetic comparison - avoids extra errors
|
|
# when above read fails in an unexpected way...
|
|
if [ "$_running_threads" != "$_configured_threads" ]; then
|
|
echo "Attempting to correct number of nfsd threads from ${_running_threads} to ${_configured_threads}"
|
|
echo "$_configured_threads" >"$_threads_file"
|
|
fi
|
|
}
|
|
|
|
##################################################
|
|
# list share directories
|
|
|
|
nfs_monitor_list_shares()
|
|
{
|
|
_cache_file="${CTDB_NFS_CALLOUT_STATE_DIR}/list_shares_cache"
|
|
# -nt operator is well supported in Linux: dash, bash, ksh, ...
|
|
# shellcheck disable=SC2039,SC3013
|
|
if [ ! -r "$nfs_exports_file" ] || [ ! -r "$_cache_file" ] ||
|
|
[ "$nfs_exports_file" -nt "$_cache_file" ]; then
|
|
mkdir -p "$CTDB_NFS_CALLOUT_STATE_DIR"
|
|
# We could just use the contents of $nfs_exports_file.
|
|
# However, let's regard that file as internal to NFS and use
|
|
# exportfs, which is the public API.
|
|
if ! _exports=$(exportfs -v); then
|
|
echo "WARNING: failed to run exportfs to list NFS shares" >&2
|
|
return
|
|
fi
|
|
|
|
echo "$_exports" |
|
|
grep '^/' |
|
|
sed -e 's@[[:space:]][[:space:]]*[^[:space:]()][^[:space:]()]*([^[:space:]()][^[:space:]()]*)$@@' |
|
|
sort -u >"$_cache_file"
|
|
fi
|
|
|
|
cat "$_cache_file"
|
|
}
|
|
|
|
##################################################
|
|
|
|
nfs_register()
|
|
{
|
|
cat <<EOF
|
|
shutdown
|
|
startup
|
|
stop
|
|
start
|
|
monitor-list-shares
|
|
monitor-post
|
|
EOF
|
|
}
|
|
|
|
##################################################
|
|
|
|
case "$1" in
|
|
shutdown)
|
|
nfs_shutdown
|
|
;;
|
|
startup)
|
|
nfs_startup
|
|
;;
|
|
stop)
|
|
service_stop "$2"
|
|
;;
|
|
start)
|
|
service_start "$2"
|
|
;;
|
|
monitor-list-shares)
|
|
nfs_monitor_list_shares
|
|
;;
|
|
monitor-post)
|
|
nfs_check_thread_count
|
|
;;
|
|
register)
|
|
nfs_register
|
|
;;
|
|
monitor-pre | releaseip | takeip | releaseip-pre | takeip-pre)
|
|
# Not required/implemented
|
|
:
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|