#!/sbin/runscript
# Copyright 1999-2005 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/nfs,v 1.14 2007/03/24 10:14:43 vapier Exp $

#---------------------------------------------------------------------------
# This script starts/stops the following
#	rpc.statd if necessary (also checked by init.d/nfsmount)
#	rpc.rquotad if exists (from quota package)
#	rpc.nfsd
#	rpc.mountd
#---------------------------------------------------------------------------

# NB: Config is in /etc/conf.d/nfs

opts="reload"

# This variable is used for controlling whether or not to run exportfs -ua;
# see stop() for more information
restarting=no

# The binary locations
exportfs=/usr/sbin/exportfs
    gssd=/usr/sbin/rpc.gssd
  idmapd=/usr/sbin/rpc.idmapd
  mountd=/usr/sbin/rpc.mountd
    nfsd=/usr/sbin/rpc.nfsd
 rquotad=/usr/sbin/rpc.rquotad
   statd=/sbin/rpc.statd
 svcgssd=/usr/sbin/rpc.svcgssd

depend() {
	use ypbind net
	need portmap
	after quota
}

mkdir_nfsdirs() {
	local d
	for d in /var/lib/nfs/{rpc_pipefs,v4recovery,v4root} ; do
		[[ ! -d ${d} ]] && mkdir -p "${d}"
	done
}

mount_pipefs() {
	if grep -q rpc_pipefs /proc/filesystems ; then
		if ! grep -q "rpc_pipefs /var/lib/nfs/rpc_pipefs" /proc/mounts ; then
			ebegin "Mounting RPC pipefs"
			mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs
			eend $?
		fi
	fi
}

umount_pipefs() {
	if [[ ${restarting} == "no" ]] ; then
		if grep -q "rpc_pipefs /var/lib/nfs/rpc_pipefs" /proc/mounts ; then
			ebegin "Unmounting RPC pipefs"
			umount /var/lib/nfs/rpc_pipefs
			eend $?
		fi
	fi
}

start_gssd() {
	[[ ! -x ${gssd} || ! -x ${svcgssd} ]] && return 0
	local ret1 ret2

	ebegin "Starting gssd"
	${gssd} ${RPCGSSDDOPTS}
	ret1=$?
	eend ${ret1}

	ebegin "Starting svcgssd"
	${svcgssd} ${RPCSVCGSSDDOPTS}
	ret2=$?
	eend ${ret2}

	return $((${ret1} + ${ret2}))
}

stop_gssd() {
	[[ ! -x ${gssd} || ! -x ${svcgssd} ]] && return 0
	local ret

	ebegin "Stopping gssd"
	start-stop-daemon --stop --quiet --exec ${gssd}
	ret1=$?
	eend ${ret1}

	ebegin "Stopping svcgssd"
	start-stop-daemon --stop --quiet --exec ${svcgssd}
	ret2=$?
	eend ${ret2}

	return $((${ret1} + ${ret2}))
}

start_idmapd() {
	[[ ! -x ${idmapd} ]] && return 0

	ebegin "Starting idmapd"
	${idmapd} ${RPCIDMAPDOPTS}
	eend $?
}

stop_idmapd() {
	[[ ! -x ${idmapd} ]] && return 0
	local ret

	ebegin "Stopping idmapd"
	start-stop-daemon --stop --quiet --exec ${idmapd}
	ret=$?
	eend ${ret}

	umount_pipefs

	return ${ret}
}

start_statd() {
	# Don't start rpc.statd if already started by init.d/nfsmount
	killall -0 rpc.statd &>/dev/null && return 0
	ebegin "Starting NFS statd"
	start-stop-daemon --start --quiet --exec \
		$statd -- $RPCSTATDOPTS 1>&2
	eend $? "Error starting NFS statd"
}

stop_statd() {
	# Don't stop rpc.statd if it's in use by init.d/nfsmount.
	mount -t nfs | grep -q . && return 0
	# Make sure it's actually running
	killall -0 rpc.statd &>/dev/null || return 0
	# Okay, all tests passed, stop rpc.statd
	ebegin "Stopping NFS statd"
	start-stop-daemon --stop --quiet --exec $statd 1>&2
	eend $? "Error stopping NFS statd"
}

waitfor_exportfs() {
	local pid=$1
	( sleep ${EXPORTFSTIMEOUT:-30}; kill -9 $pid &>/dev/null ) &
	wait $1
}

start() {
	# Make sure nfs support is loaded in the kernel #64709
	if [[ -e /proc/modules ]] && ! grep -qs nfsd /proc/filesystems ; then
		modprobe nfsd &> /dev/null
	fi

	# This is the new "kernel 2.6 way" to handle the exports file
	if grep -qs nfsd /proc/filesystems ; then
		if ! grep -qs "^nfsd[[:space:]]/proc/fs/nfsd[[:space:]]" /proc/mounts ; then
			ebegin "Mounting nfsd filesystem in /proc"
			mount -t nfsd nfsd /proc/fs/nfsd
			eend $? "Error mounting nfsd filesystem in /proc"
		fi
	fi
	# now that nfsd is mounted inside /proc, we can safely start mountd later

	mkdir_nfsdirs

	mount_pipefs
	start_idmapd
	start_gssd
	start_statd

	# Exportfs likes to hang if networking isn't working.
	# If that's the case, then try to kill it so the
	# bootup process can continue.
	if grep -q '^/' /etc/exports &>/dev/null; then
		ebegin "Exporting NFS directories"
		$exportfs -r 1>&2 &
		waitfor_exportfs $!
		eend $? "Error exporting NFS directories"
	fi

	if [ -x $rquotad ]; then
		ebegin "Starting NFS rquotad"
		start-stop-daemon --start --quiet --exec \
			$rquotad -- $RPCRQUOTADOPTS 1>&2
		eend $? "Error starting NFS rquotad"
	fi

	ebegin "Starting NFS daemon"
	start-stop-daemon --start --quiet --exec \
		$nfsd --name nfsd -- $RPCNFSDCOUNT 1>&2
	eend $? "Error starting NFS daemon"

	# Start mountd
	ebegin "Starting NFS mountd"
	start-stop-daemon --start --quiet --exec \
		$mountd -- $RPCMOUNTDOPTS 1>&2
	eend $? "Error starting NFS mountd"
}

stop() {
	# Don't check NFSSERVER variable since it might have changed,
	# instead use --oknodo to smooth things over
	ebegin "Stopping NFS mountd"
	start-stop-daemon --stop --quiet --oknodo \
		--exec $mountd 1>&2
	eend $? "Error stopping NFS mountd"

	# nfsd sets its process name to [nfsd] so don't look for $nfsd
	ebegin "Stopping NFS daemon"
	start-stop-daemon --stop --quiet --oknodo \
		--name nfsd --user root --signal 2 1>&2
	eend $? "Error stopping NFS daemon"

	if [ -x $rquotad ]; then
		ebegin "Stopping NFS rquotad"
		start-stop-daemon --stop --quiet --oknodo \
			--exec $rquotad 1>&2
		eend $? "Error stopping NFS rquotad"
	fi

	# When restarting the NFS server, running "exportfs -ua" probably
	# isn't what the user wants.  Running it causes all entries listed
	# in xtab to be removed from the kernel export tables, and the
	# xtab file is cleared. This effectively shuts down all NFS
	# activity, leaving all clients holding stale NFS filehandles,
	# *even* when the NFS server has restarted.
	#
	# That's what you would want if you were shutting down the NFS
	# server for good, or for a long period of time, but not when the
	# NFS server will be running again in short order.  In this case,
	# then "exportfs -r" will reread the xtab, and all the current
	# clients will be able to resume NFS activity, *without* needing
	# to umount/(re)mount the filesystem.
	if [ "$restarting" = no ]; then
		ebegin "Unexporting NFS directories"
		# Exportfs likes to hang if networking isn't working.
		# If that's the case, then try to kill it so the
		# shutdown process can continue.
		$exportfs -ua 1>&2 &
		waitfor_exportfs $!
		eend $? "Error unexporting NFS directories"
	fi

	stop_statd
	stop_gssd
	stop_idmapd
	umount_pipefs

	return 0
}

reload() {
	# Exportfs likes to hang if networking isn't working.
	# If that's the case, then try to kill it so the
	# bootup process can continue.
	ebegin "Reloading /etc/exports"
	$exportfs -r 1>&2 &
	waitfor_exportfs $!
	eend $? "Error exporting NFS directories"
}

restart() {
	# See long comment in stop() regarding "restarting" and exportfs -ua
	restarting=yes
	svc_stop
	svc_start
}
