#!/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. nfs_exports_file="${CTDB_NFS_EXPORTS_FILE:-/var/lib/nfs/etab}" # Do not set CTDB_NFS_DISTRO_STYLE - it isn't a configuration # variable, just a hook for testing. To change the style, edit the # default value below. nfs_distro_style="${CTDB_NFS_DISTRO_STYLE:-systemd-redhat}" # As above, edit the default value below. CTDB_SYS_ETCDIR is a # test variable only. etc_dir="${CTDB_SYS_ETCDIR:-/etc}" # 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_dir}/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_dir}/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_dir}/default/nfs-kernel-server" nfs_rquotad_config="${etc_dir}/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 <"${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 -r _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 <