#!/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:-sysvinit-redhat}" 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="" nfs_mountd_service="" nfs_status_service="" nfs_rquotad_service="" 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 <"${PROCFS_PATH}/fs/nfsd/threads" basic_stop "nfs" >/dev/null 2>&1 || true pkill -9 nfsd ;; nlockmgr) basic_stop "nfslock" >/dev/null 2>&1 || true ;; mountd) if [ -n "$nfs_mountd_service" ] ; then service "$nfs_mountd_service" stop return fi # Default to stopping by hand killall -q -9 rpc.mountd ;; rquotad) if [ -n "$nfs_rquotad_service" ] ; then service "$nfs_rquotad_service" stop return fi # Default to stopping by hand killall -q -9 rpc.rquotad ;; status) if [ -n "$nfs_status_service" ] ; then service "$nfs_status_service" stop return fi # Default to stopping by hand killall -q -9 rpc.statd ;; *) usage esac } service_start () { case "$1" in nfs) basic_start "nfs" ;; nlockmgr) basic_start "nfslock" ;; mountd) if [ -n "$nfs_mountd_service" ] ; then service "$nfs_mountd_service" start return fi # Default to starting by hand nfs_load_config if [ -z "$RPCMOUNTDOPTS" ] ; then RPCMOUNTDOPTS="${MOUNTD_PORT:+-p }$MOUNTD_PORT" fi # shellcheck disable=SC2086 rpc.mountd $RPCMOUNTDOPTS ;; rquotad) if [ -n "$nfs_rquotad_service" ] ; then service "$nfs_rquotad_service" start return fi # Default to starting by hand nfs_load_config "$nfs_rquotad_config" if [ -z "$RPCRQUOTADOPTS" ] ; then RPCRQUOTADOPTS="${RQUOTAD_PORT:+-p }$RQUOTAD_PORT" fi # shellcheck disable=SC2086 rpc.rquotad $RPCRQUOTADOPTS ;; status) if [ -n "$nfs_status_service" ] ; then service "$nfs_status_service" start return fi # Default to starting by hand 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 ;; *) usage esac } ################################################## # service init startup and final shutdown nfs_shutdown () { basic_stop "nfs" } nfs_startup () { basic_stop "nfs" || true basic_start "nfs" _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}}" [ -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 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 <