diff --git a/rgmanager/src/resources/netfs.sh b/rgmanager/src/resources/netfs.sh
index 93f977397..b67932827 100755
--- a/rgmanager/src/resources/netfs.sh
+++ b/rgmanager/src/resources/netfs.sh
@@ -1,408 +1,481 @@
 #!/bin/bash
 
 #
 # NFS/CIFS file system mount/umount/etc. agent
 #
 #
 # Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
 # Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
 # of the License, or (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #
 
 . $(dirname $0)/utils/fs-lib.sh
 
 do_metadata()
 {
 	cat <<EOT
 <?xml version="1.0" ?>
 <!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
 <resource-agent name="netfs" version="rgmanager 2.0">
     <version>1.0</version>
 
     <longdesc lang="en">
         This defines an NFS/CIFS mount for use by cluster services.
     </longdesc>
     <shortdesc lang="en">
         Defines an NFS/CIFS file system mount.
     </shortdesc>
 
     <parameters>
         <parameter name="name" primary="1">
 	    <longdesc lang="en">
 	        Symbolic name for this file system.
 	    </longdesc>
             <shortdesc lang="en">
                 File System Name
             </shortdesc>
 	    <content type="string"/>
         </parameter>
 
         <parameter name="mountpoint" unique="1" required="1">
 	    <longdesc lang="en">
 	        Path in file system heirarchy to mount this file system.
 	    </longdesc>
             <shortdesc lang="en">
                 Mount Point
             </shortdesc>
 	    <content type="string"/>
         </parameter>
 
         <parameter name="host" required="1">
 	    <longdesc lang="en">
 	    	Server IP address or hostname
 	    </longdesc>
             <shortdesc lang="en">
 	    	IP or Host
             </shortdesc>
 	    <content type="string"/>
         </parameter>
 
         <parameter name="export" required="1">
 	    <longdesc lang="en">
 	    	NFS Export directory name or CIFS share
 	    </longdesc>
             <shortdesc lang="en">
 	    	Export
             </shortdesc>
 	    <content type="string"/>
         </parameter>
 
         <parameter name="fstype" required="0">
 	    <longdesc lang="en">
 	    	File System type (nfs, nfs4 or cifs)
 	    </longdesc>
             <shortdesc lang="en">
 	    	File System Type
             </shortdesc>
 	    <content type="string"/>
         </parameter>
 
         <parameter name="no_unmount" required="0">
 	    <longdesc lang="en">
 	    	Do not unmount the filesystem during a stop or relocation operation
 	    </longdesc>
             <shortdesc lang="en">
 	    	Skip unmount opration
             </shortdesc>
 	    <content type="boolean"/>
         </parameter>
 
         <parameter name="force_unmount">
             <longdesc lang="en">
                 If set, the cluster will kill all processes using 
                 this file system when the resource group is 
                 stopped.  Otherwise, the unmount will fail, and
                 the resource group will be restarted.
             </longdesc>
             <shortdesc lang="en">
                 Force Unmount
             </shortdesc>
 	    <content type="boolean"/>
         </parameter>
 
         <parameter name="self_fence">
             <longdesc lang="en">
                 If set and unmounting the file system fails, the node will
                 immediately reboot.  Generally, this is used in conjunction
                 with force_unmount support, but it is not required.
             </longdesc>
             <shortdesc lang="en">
                 Seppuku Unmount
             </shortdesc>
             <content type="boolean"/>
         </parameter>
 
         <parameter name="options">
             <longdesc lang="en">
 	    	Provides a list of mount options.  If none are specified,
 		the NFS file system is mounted -o sync.
             </longdesc>
             <shortdesc lang="en">
                 Mount Options
             </shortdesc>
 	    <content type="string"/>
         </parameter>
 
     </parameters>
 
     <actions>
         <action name="start" timeout="900"/>
 	<action name="stop" timeout="30"/>
 	<!-- Recovery isn't possible; we don't know if resources are using
 	     the file system. -->
 
 	<!-- Checks to see if it's mounted in the right place -->
 	<action name="status" interval="1m" timeout="10"/>
 	<action name="monitor" interval="1m" timeout="10"/>
 
 	<!-- Checks to see if we can read from the mountpoint -->
 	<action name="status" depth="10" timeout="30" interval="5m"/>
 	<action name="monitor" depth="10" timeout="30" interval="5m"/>
 
 	<!-- Checks to see if we can write to the mountpoint (if !ROFS) -->
 	<action name="status" depth="20" timeout="30" interval="10m"/>
 	<action name="monitor" depth="20" timeout="30" interval="10m"/>
 
 	<action name="meta-data" timeout="5"/>
 	<action name="validate-all" timeout="5"/>
     </actions>
 
     <special tag="rgmanager">
         <child type="nfsexport" forbid="1"/>
         <child type="nfsclient" forbid="1"/>
     </special>
 </resource-agent>
 EOT
 }
 
 
 verify_host()
 {
 	if [ -z "$OCF_RESKEY_host" ]; then
 	       ocf_log err "No server hostname or IP address specified."
 	       return 1
 	fi
 
 	host $OCF_RESKEY_host 2>&1 | grep -vq "not found"
 	if [ $? -eq 0 ]; then
 		return 0
 	fi
 
 	ocf_log err "Hostname or IP address \"$OCF_RESKEY_host\" not valid"
 
 	return $OCF_ERR_ARGS
 }
 
 
 verify_fstype()
 {
 	# Auto detect?
 	[ -z "$OCF_RESKEY_fstype" ] && return 0
 
 	case $OCF_RESKEY_fstype in
 	nfs|nfs4|cifs)
 		return 0
 		;;
 	*)
 		ocf_log err "File system type $OCF_RESKEY_fstype not supported"
 		return $OCF_ERR_ARGS
 		;;
 	esac
 }
 
 
 verify_options()
 {
 	declare -i ret=0
 
 	#
 	# From mount(1)
 	#
 	for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
 		case $o in
 		async|atime|auto|defaults|dev|exec|_netdev|noatime)
 			continue
 			;;
 		noauto|nodev|noexec|nosuid|nouser|ro|rw|suid|sync)
 			continue
 			;;
 		dirsync|user|users)
 			continue
 			;;
 		esac
 
 		case $OCF_RESKEY_fstype in
 		cifs)
 			continue
 			;;
 		nfs|nfs4)
 			case $o in
 			#
 			# NFS / NFS4 common
 			#
 			rsize=*|wsize=*|timeo=*|retrans=*|acregmin=*)
 				continue
 				;;
 			acregmax=*|acdirmin=*|acdirmax=*|actimeo=*)
 				continue
 				;;
 			retry=*|port=*|bg|fg|soft|hard|intr|cto|ac|noac)
 				continue
 				;;
 			esac
 
 			#
 			# NFS v2/v3 only
 			#
 			if [ "$OCF_RESKEY_fstype" = "nfs" ]; then
 				case $o in
 				mountport=*|mounthost=*)
 					continue
 					;;
 				mountprog=*|mountvers=*|nfsprog=*|nfsvers=*)
 					continue
 					;;
 				namelen=*)
 					continue
 					;;
 				tcp|udp|lock|nolock)
 					continue
 					;;
 				esac
 			fi
 
 			#
 			# NFS4 only
 			#
 			if [ "$OCF_RESKEY_fstype" = "nfs4" ]; then
 				case $o in
 				proto=*|clientaddr=*|sec=*)
 					continue
 					;;
 				esac
 			fi
 
 			;;
 		esac
 
 		ocf_log err "Option $o not supported for $OCF_RESKEY_fstype"
 		ret=$OCF_ERR_ARGS
 	done
 
 	return $ret
 }
 
 
 do_validate()
 {
 	verify_name || return $OCF_ERR_ARGS
 	verify_fstype|| return $OCF_ERR_ARGS
 	verify_host || return $OCF_ERR_ARGS
 	verify_mountpoint || return $OCF_ERR_ARGS
 	verify_options || return $OCF_ERR_ARGS
 	# verify_target || return $OCF_ERR_ARGS
 }
 
 
 #
 # Override real_device to use fs-lib's functions for start/stop_filesystem
 #
 real_device() {
 	export REAL_DEVICE="$1"
 }
 
 
 #
 # do_mount - nfs / cifs are mounted differently than blockdevs
 #
 do_mount() {
 	declare opts=""
 	declare mount_options=""
 	declare ret_val
 	declare mp="$OCF_RESKEY_mountpoint"
 
 	#
 	# Get the filesystem type, if specified.
 	#
 	fstype_option=""
 	fstype=${OCF_RESKEY_fstype}
 		case "$fstype" in
 	""|"[ 	]*")
 		fstype=""
 		;;
 	*)	# found it
 		fstype_option="-t $fstype"
 		;;
 	esac
 
 	#
 	# Get the mount options, if they exist.
 	#
 	mount_options=""
 	opts=${OCF_RESKEY_options}
 	case "$opts" in 
 	""|"[ 	]*")
 		opts=""
 		;;
 	*)	# found it
 		mount_options="-o $opts"
 		;;
 	esac
 
         case $OCF_RESKEY_fstype in
 	nfs|nfs4)
 		mount -t $OCF_RESKEY_fstype $mount_options $OCF_RESKEY_host:"$OCF_RESKEY_export" "$mp"
 		;;
 	cifs)
 		mount -t $OCF_RESKEY_fstype $mount_options //$OCF_RESKEY_host/"$OCF_RESKEY_export" "$mp"
 		;;
 	esac
 
 	ret_val=$?
 	if [ $ret_val -ne 0 ]; then
 		ocf_log err "\
 'mount $fstype_option $mount_options $OCF_RESKEY_host:$OCF_RESKEY_export $mp' failed, error=$ret_val"
 		return 1
 	fi
 	
 	return 0
 }
 
+do_nfs_rpc_check() {
+	# see man nfs TRANSPORT PROTOCOL section for defaults
+	local nfsproto=tcp
+	local nfsmountproto=udp
+
+	# follow the same logic as mount.nfs option parser.
+	# the rightmost option wins over previous ones, so don't break when
+	# we find something.
+
+	for o in $(echo ${OCF_RESKEY_options} | sed -e s/,/\ /g); do
+		if echo $o | grep -q "^proto=" ; then
+			nfsproto="$(echo $o | cut -d "=" -f 2)"
+		fi
+		if echo $o | grep -q "^mountproto=" ; then
+			nfsmountproto="$(echo $o | cut -d "=" -f 2)"
+		fi
+		case $o in
+		tcp)	nfsproto=tcp;;
+		udp)	nfsproto=udp;;
+		rdma)	nfsproto=rdma;;
+		esac
+	done
+
+	ocf_log debug "Testing generic rpc access on server ${OCF_RESKEY_host} with protocol $nfsproto"
+	if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} > /dev/null 2>&1; then
+		ocf_log alert "RPC server on ${OCF_RESKEY_host} with $nfsproto is not responding"
+		return 1
+	fi
+
+	ocf_log debug "Testing nfs rcp access on server ${OCF_RESKEY_host} with protocol $nfsproto"
+	if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} nfs > /dev/null 2>&1; then
+		ocf_log alert "NFS server on ${OCF_RESKEY_host} with $nfsproto is not responding"
+		return 1 
+	fi
+
+	if [ "$OCF_RESKEY_fstype" = nfs ]; then
+		ocf_log debug "Testing mountd rpc access on server ${OCF_RESKEY_host} with protocol $nfsmountproto"
+		if ! rpcinfo -T $nfsmountproto ${OCF_RESKEY_host} mountd; then
+			ocf_log alert "MOUNTD server on ${OCF_RESKEY_host} with $nfsmountproto is not responding"
+			return 1
+		fi
+	fi
+
+	return 0
+}
+
+do_pre_unmount() {
+	case $OCF_RESKEY_fstype in
+	nfs|nfs4)
+		if [ "$self_fence" != $YES ]; then
+			ocf_log debug "Skipping pre unmount checks: self_fence is disabled"
+			return 0
+		fi
+
+		is_mounted "$dev" "$mp"
+		case $? in
+		$NO)
+			ocf_log debug "Skipping pre unmount checks: device is not mounted"
+			return 0
+			;;
+		esac
+
+		ocf_log info "pre unmount: checking if nfs server ${OCF_RESKEY_host} is alive"
+		if ! do_nfs_rpc_check; then
+			ocf_log alert "NFS server not responding - REBOOTING"
+			sleep 2
+			reboot -fn
+		fi
+		;;
+	esac
+
+	return 0
+}
 
 do_force_unmount() {
         case $OCF_RESKEY_fstype in
 	nfs|nfs4)
 		ocf_log warning "Calling 'umount -f $mp'"
 		umount -f "$OCF_RESKEY_mountpoint"
 		return $?
 		;;
 	*)
 		;;
 	esac
 
 	return 1	# Returning 1 lets stop_filesystem do add'l checks
 }
 
 
 populate_defaults()
 {
 	if [ -z "$OCF_RESKEY_fstype" ]; then
 		export OCF_RESKEY_fstype=nfs
 	fi
 
 
         case $OCF_RESKEY_fstype in
 	nfs|nfs4)
 		export OCF_RESKEY_device="$OCF_RESKEY_host:$OCF_RESKEY_export"
 		if [ -z "$OCF_RESKEY_options" ]; then
 			export OCF_RESKEY_options=sync,soft,noac
 		fi
 		;;
 	cifs)
 		export OCF_RESKEY_device="//$OCF_RESKEY_host/$OCF_RESKEY_export"
 		if [ -z "$OCF_RESKEY_options" ]; then
 			export OCF_RESKEY_options=guest
 		fi
 		;;
 	esac
 }
 
 
 #
 # Main...
 #
 populate_defaults
 main $*
diff --git a/rgmanager/src/resources/utils/fs-lib.sh b/rgmanager/src/resources/utils/fs-lib.sh
index c78b143da..e3ead2205 100644
--- a/rgmanager/src/resources/utils/fs-lib.sh
+++ b/rgmanager/src/resources/utils/fs-lib.sh
@@ -1,1166 +1,1170 @@
 #!/bin/bash
 #
 # Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
 # Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
 # of the License, or (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #
 
 #
 # File system common functions
 #
 
 LC_ALL=C
 LANG=C
 PATH=/bin:/sbin:/usr/bin:/usr/sbin
 export LC_ALL LANG PATH
 
 # Private return codes
 FAIL=2
 NO=1
 YES=0
 YES_STR="yes"
 
 [ -z "$OCF_RESOURCE_INSTANCE" ] && export OCF_RESOURCE_INSTANCE="filesystem:$OCF_RESKEY_name"
 
 #
 # Using a global to contain the return value saves
 # clone() operations.  This is important to reduce
 # resource consumption during status checks.
 #
 # There is no way to return a string from a function
 # in bash without cloning the process, which is exactly
 # what we are trying to avoid.  So, we have to resort
 # to using a dedicated global variables.
 declare REAL_DEVICE
 declare STRIP_SLASHES=""
 declare FINDMNT_OUTPUT=""
 
 #
 # Stub ocf_log function for when we are using
 # quick_status, since ocf_log generally forks (and
 # sourcing ocf-shellfuncs forks -a lot-).
 #
 ocf_log()
 {
 	echo $*
 }
 
 #
 # Assume NFS_TRICKS are not available until we are
 # proved otherwise.
 #
 export NFS_TRICKS=1
 
 #
 # Quick status doesn't fork() or clone() when using
 # device files directly.  (i.e. not symlinks, LABEL= or
 # UUID=
 #
 if [ "$1" = "status" -o "$1" = "monitor" ] &&
    [ "$OCF_RESKEY_quick_status" = "1" ]; then
 	echo Using Quick Status
 
 	# XXX maybe we can make ocf-shellfuncs have a 'quick' mode too?
 	export OCF_SUCCESS=0
 	export OCF_ERR_GENERIC=1
 else
 	#
 	# Grab nfs lock tricks if available
 	#
 	if [ -f "$(dirname $0)/svclib_nfslock" ]; then
 		. $(dirname $0)/svclib_nfslock
 		NFS_TRICKS=0
 	fi
 
 	. $(dirname $0)/ocf-shellfuncs
 fi
 
 
 verify_name()
 {
 	if [ -z "$OCF_RESKEY_name" ]; then
 		ocf_log err "No file system name specified."
 		return $OCF_ERR_ARGS
 	fi
 	return $OCF_SUCCESS
 }
 
 
 verify_mountpoint()
 {
 	if [ -z "$OCF_RESKEY_mountpoint" ]; then
 		ocf_log err "No mount point specified."
 		return $OCF_ERR_ARGS
 	fi
 
 	if ! [ -e "$OCF_RESKEY_mountpoint" ]; then
 		ocf_log info "Mount point $OCF_RESKEY_mountpoint will be "\
 				"created at mount time."
 		return $OCF_SUCCESS
 	fi
 
 	[ -d "$OCF_RESKEY_mountpoint" ] && return $OCF_SUCCESS
 
 	ocf_log err "$OCF_RESKEY_mountpoint exists but is not a directory."
 
 	return $OCF_ERR_ARGS
 }
 
 
 #
 # This used to be called using $(...), but doing this causes bash
 # to set up a pipe and clone().  So, the output of this function is
 # stored in the global variable REAL_DEVICE, declared previously.
 #
 real_device()
 {
 	declare dev="$1"
 	declare realdev
 
 	REAL_DEVICE=""
 
 	[ -z "$dev" ] && return $OCF_ERR_ARGS
 
 	# Oops, we have a link.  Sorry, this is going to fork.
 	if [ -h "$dev" ]; then
 		realdev=$(readlink -f $dev)
 		if [ $? -ne 0 ]; then
 			return $OCF_ERR_ARGS
 		fi
 		REAL_DEVICE="$realdev"
 		return $OCF_SUCCESS
 	fi
 
 	# If our provided blockdev is a device, we are done
 	if [ -b "$dev" ]; then
 		REAL_DEVICE="$dev"
 		return $OCF_SUCCESS
 	fi
 
 	# It's not a link, it's not a block device.  If it also
 	# does not match UUID= or LABEL=, then findfs is not
 	# going to find anything useful, so we should quit now.
 	if [ "${dev/UUID=/}" = "$dev" ] &&
 	   [ "${dev/LABEL=/}" = "$dev" ]; then
 		return $OCF_ERR_GENERIC
 	fi
 
 	# When using LABEL= or UUID=, we can't save a fork.
 	realdev=$(findfs "$dev" 2> /dev/null)
 	if [ -n "$realdev" ] && [ -b "$realdev" ]; then
 		REAL_DEVICE="$realdev"
 		return $OCF_SUCCESS
 	fi
 
 	return $OCF_ERR_GENERIC
 }
 
 
 verify_device()
 {
 	declare realdev
 
 	if [ -z "$OCF_RESKEY_device" ]; then
 	       ocf_log err "No device or label specified."
 	       return $OCF_ERR_ARGS
 	fi
 
 	real_device "$OCF_RESKEY_device"
 	realdev="$REAL_DEVICE"
 	if [ -n "$realdev" ]; then
 		if [ "$realdev" != "$OCF_RESKEY_device" ]; then
 			ocf_log info "Specified $OCF_RESKEY_device maps to $realdev"
 		fi
 		return $OCF_SUCCESS
 	fi
 
 	ocf_log err "Device or label \"$OCF_RESKEY_device\" not valid"
 
 	return $OCF_ERR_ARGS
 }
 
 ##
 # Tries to use findmnt util to return list
 # of mountpoints for a device
 #
 # Global variables are used to reduce forking when capturing stdout.
 #
 # Return values
 # 0 - device mount points found, mountpoint list returned to FINDMNT_OUTPUT global variable
 # 1 - device mount not found
 # 2 - findmnt tool isn't found
 #
 ##
 try_findmnt()
 {
 	FINDMNT_OUTPUT=""
 
 	which findmnt > /dev/null 2>&1
 	if [ $? -eq 0 ]; then
 		FINDMNT_OUTPUT=$(findmnt -o TARGET --noheadings $1)
 		if [ $? -ne 0 ]; then
 			return 1
 		else
 			return 0
 		fi
 	fi
 
 	return 2
 }
 
 ##
 # Returns result in global variable to reduce forking
 ##
 strip_trailing_slashes()
 {
 	local tmp=$1
 	while [ "${tmp#${tmp%?}}" = "/" ]
 	do
 		tmp="${tmp%/}"
 	done
 
 	STRIP_SLASHES="$tmp"
 }
 
 #
 # kill_procs_using_mount mount_point [signal]
 # 
 # Kill any processes using the specified mountpoint, using the optional 
 # specified signal. This is used in place of fuser to avoid it becoming
 # blocked while following symlinks to an unresponsive file system.  
 # Defaults to SIGKILL if no signal specified. 
 # 
 kill_procs_using_mount () {
 	declare mp
 	declare procs
 
 	if [ $# -lt 1 -o -z "$1" ]; then
 		ocf_log err "Usage: kill_procs_using_mount mount_point [signal]"
 		return $FAIL
 	fi
 
 	strip_trailing_slashes "$1"
 	mp="$STRIP_SLASHES"
 
 	if [ -z "$mp" ]; then
 		ocf_log err "Usage: kill_procs_using_mount mount_point [signal]"
 		return $FAIL
 	fi
 
 	# anything held open in mount point after the slash
 	procs=$(find /proc/[0-9]*/fd/ -type l -lname "${mp}/*" -or -lname "${mp}" 2>/dev/null | awk -F/ '{print $3}' | uniq)
 
 	for pid in $procs; do
 		if [ -n "$2" ]; then
 			kill -s $2 $pid
 		else
 			kill -s KILL $pid
 		fi	
 	done
 
 	return $SUCCESS
 }
 
 #
 # mount_in_use device mount_point
 #
 # Check to see if either the device or mount point are in use anywhere on
 # the system.  It is not required that the device be mounted on the named
 # moint point, just if either are in use.
 #
 mount_in_use () {
 	declare mp tmp_mp
 	declare dev tmp_dev
 	declare junka junkb junkc junkd
 	declare res=$FAIL
 	declare findmnt_res=2
 
 	if [ $# -ne 2 ]; then
 		ocf_log err "Usage: mount_in_use device mount_point".
 		return $FAIL
 	fi
 
 	dev="$1"
 	mp="$2"
 
 	# First try and find out if the device has a mount point by
 	# attempting to use the findmnt tool. It is much faster than
 	# iterating through /proc/mounts
 	try_findmnt $dev
 	findmnt_res=$?
 	if [ $findmnt_res -eq 0 ]; then
 		case $OCF_RESKEY_fstype in
 		cifs|nfs|nfs4)
 			# -r means to include '/' character and not treat it as escape character
 			while read -r tmp_mp
 			do
 				if [ "$tmp_mp" = "$mp" ]; then
 					return $YES
 				fi
 			done < <(echo $FINDMNT_OUTPUT)
 			;;
 		*)
 			return $YES
 			;;
 		esac
 	fi
 
 	while read -r tmp_dev tmp_mp junka junkb junkc junkd; do
 		# Does the device match? We might have already tried findmnt
 		# which is why this could get skipped
 		if [ $findmnt_res -eq 2 ]; then
 			if [ "${tmp_dev:0:1}" != "-" ]; then
 				# XXX fork/clone warning XXX
 				tmp_dev="$(printf "$tmp_dev")"
 			fi
 
 			strip_trailing_slashes "$tmp_dev"
 			tmp_dev="$STRIP_SLASHES"
 			if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then
 				case $OCF_RESKEY_fstype in
 				cifs|nfs|nfs4)
 					;;
 				*)
 					return $YES
 					;;
 				esac
 			fi
 		fi
 
 		# Mountpoint from /proc/mounts containing spaces will
 		# have spaces represented in octal.  printf takes care
 		# of this for us.
 		tmp_mp="$(printf "$tmp_mp")"
 
 		if [ -n "$tmp_mp" -a "$tmp_mp" = "$mp" ]; then
 			return $YES
 		fi
 	done < <(cat /proc/mounts)
 
 	return $NO
 }
 
 ##
 # Returns whether or not the device is mounted.
 # If the mountpoint does not match the one provided, the
 # mount point found is printed to stdout.
 ##
 real_mountpoint()
 {
 	declare dev=$1
 	declare mp=$2
 	declare ret=$NO
 	declare tmp_mp
 	declare tmp_dev
 	declare found=1
 	declare poss_mp=""
 
 	try_findmnt $dev
 	case $? in
 	0)  #findmnt found mount points, loop through them to find a match
 
 		# -r means to include '/' character and not treat it as escape character
 		while read -r tmp_mp
 		do
 			ret=$YES
 			if [ "$tmp_mp" != "$mp" ]; then
 				poss_mp=$tmp_mp
 			else
 				found=0
 				break
 			fi
 		done < <(echo $FINDMNT_OUTPUT)
 		;;
 	1)
 		# findmnt found no mount points for the device
 		return $NO
 		;;
 	2)  # findmnt tool could not be used.
 		# Using slow method reading /proc/mounts dir.
 		while read -r tmp_dev tmp_mp junk_a junk_b junk_c junk_d
 		do
 			if [ "${tmp_dev:0:1}" != "-" ]; then
 				# XXX fork/clone warning XXX
 				tmp_dev="$(printf "$tmp_dev")"
 			fi
 
 			# CIFS mounts can sometimes have trailing slashes
 			# in their first field in /proc/mounts, so strip them.
 			strip_trailing_slashes "$tmp_dev"
 			tmp_dev="$STRIP_SLASHES"
 			real_device "$tmp_dev"
 			tmp_dev="$REAL_DEVICE"
 
 			# XXX fork/clone warning XXX
 			# Mountpoint from /proc/mounts containing spaces will
 			# have spaces represented in octal.  printf takes care
 			# of this for us.
 			tmp_mp="$(printf "$tmp_mp")"
 
 			if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then
 				ret=$YES
 				#
 				# Check to see if its mounted in the right
 				# place
 				#
 				if [ -n "$tmp_mp" ]; then
 					if [ "$tmp_mp" != "$mp" ]; then
 						poss_mp=$tmp_mp
 					else
 						found=0
 						break
 					fi
 				fi
 			fi
 		done < <(cat /proc/mounts)
 	esac
 
 	if [ $found -ne 0 ]; then
 		echo "$poss_mp"
 	fi
 	return $ret
 }
 
 #
 # is_mounted device mount_point
 #
 # Check to see if the device is mounted.  Print a warning if its not
 # mounted on the directory we expect it to be mounted on.
 #
 is_mounted () {
 
 	declare mp
 	declare dev
 	declare ret=$FAIL
 	declare poss_mp
 
 	if [ $# -ne 2 ]; then
 		ocf_log err "Usage: is_mounted device mount_point"
 		return $FAIL
 	fi
 
 	real_device "$1"
 	dev="$REAL_DEVICE"
 	if [ -z "$dev" ]; then
 		ocf_log err "$OCF_RESOURCE_INSTANCE: is_mounted: Could not match $1 with a real device"
 		return $OCF_ERR_ARGS
 	fi
 
 	if [ -h "$2" ]; then
 		mp="$(readlink -f $2)"
 	else
 		mp="$2"
 	fi
 
 	# This bash glyph simply removes a trailing slash
 	# if one exists.  /a/b/ -> /a/b; /a/b -> /a/b.
 	mp="${mp%/}"
 
 	poss_mp=$(real_mountpoint "$dev" "$mp")
 	ret=$?
 
 	if [ $ret -eq $YES ] && [ -n "$poss_mp" ]; then
 		# if we made it here, then the device is mounted, but not where
 		# we expected it to be
 		case $OCF_RESKEY_fstype in
 		  cifs|nfs|nfs4)
 		    ret=$NO
 		    ;;
 		  *)
 		    ocf_log warn "Device $dev is mounted on $poss_mp instead of $mp"
 		    ;;
 		esac
 	fi
 
 
 	return $ret
 }
 
 
 #
 # is_alive mount_point
 #
 # Check to see if mount_point is alive (testing read/write)
 #
 is_alive()
 {
 	declare errcode
 	declare mount_point="$1"
 	declare file
 	declare rw
 
 	if [ $# -ne 1 ]; then
 	        ocf_log err "Usage: is_alive mount_point"
 		return $FAIL
 	fi
 
 	[ -z "$OCF_CHECK_LEVEL" ] && export OCF_CHECK_LEVEL=0
 
 	test -d "$mount_point"
 	if [ $? -ne 0 ]; then
 		ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: $mount_point is not a directory"
 		return $FAIL
 	fi
 
 	[ $OCF_CHECK_LEVEL -lt 10 ] && return $YES
 
 	# depth 10 test (read test)
 	ls "$mount_point" > /dev/null 2> /dev/null
 	errcode=$?
 	if [ $errcode -ne 0 ]; then
 		ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: failed read test on [$mount_point]. Return code: $errcode"
 		return $NO
 	fi
 
 	[ $OCF_CHECK_LEVEL -lt 20 ] && return $YES
 
 	# depth 20 check (write test)
 	rw=$YES
 	for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
                 if [ "$o" = "ro" ]; then
 		        rw=$NO
                 fi
 	done
 	if [ $rw -eq $YES ]; then
 		file=$(mktemp "$mount_point/.check_writable.$(hostname).XXXXXX")
 		if [ ! -e $file ]; then
 			ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: failed write test on [$mount_point]. Return code: $errcode"
 			return $NO
 		fi
 		rm -f $file > /dev/null 2> /dev/null
 	fi
 
 	return $YES
 }
 
 
 #
 # Decide which quota options are enabled and return a string
 # which we can pass to quotaon
 #
 quota_opts()
 {
 	declare quotaopts=""
 	declare opts="$1"
 	declare mopt
 
 	for mopt in `echo $opts | sed -e s/,/\ /g`; do
 		case $mopt in
 		quota)
 			quotaopts="gu"
 			break
 			;;
 		usrquota)
 			quotaopts="u$quotaopts"
 			continue
 			;;
 		grpquota)
 			quotaopts="g$quotaopts"
 			continue
 			;;
 		noquota)
 			quotaopts=""
 			return 0
 			;;
 		esac
 	done
 
 	echo $quotaopts
 	return 0
 }
 
 
 
 #
 # Enable quotas on the mount point if the user requested them
 #
 enable_fs_quotas()
 {
 	declare -i need_check=0
 	declare -i rv
 	declare quotaopts=""
 	declare mopt
 	declare opts="$1"
 	declare mp="$2"
 
 	if ! type quotaon &> /dev/null; then
 		ocf_log err "quotaon not found in $PATH"
 		return $OCF_ERR_GENERIC
 	fi
 
 	quotaopts=$(quota_opts $opts)
 	[ -z "$quotaopts" ] && return 0
 
 	ocf_log debug "quotaopts = $quotaopts"
 
 	# Ok, create quota files if they don't exist
 	for f in quota.user aquota.user quota.group aquota.group; do
 		if ! [ -f "$mp/$f" ]; then
 			ocf_log info "$mp/$f was missing - creating"
 			touch "$mp/$f"
 			chmod 600 "$mp/$f"
 			need_check=1
 		fi
 	done
 
 	if [ $need_check -eq 1 ]; then
 		ocf_log info "Checking quota info in $mp"
 		quotacheck -$quotaopts "$mp"
 	fi
 
 	ocf_log info "Enabling Quotas on $mp"
 	ocf_log debug "quotaon -$quotaopts \"$mp\""
 	quotaon -$quotaopts "$mp"
 	rv=$?
 	if [ $rv -ne 0 ]; then
 		# Just a warning
 		ocf_log warn "Unable to turn on quotas for $mp; return = $rv"
 	fi
 
 	return $rv
 }
 
 
 # Agent-specific actions to take before mounting
 # (if required).  Typically things like fsck.
 do_pre_mount() {
 	return 0
 }
 
 # Default mount handler - for block devices
 #
 do_mount() {
 	declare dev="$1"
 	declare mp="$2"
 	declare mount_options=""
 	declare fstype_option=""
 	declare fstype
 
 	#
 	# Get the filesystem type, if specified.
 	#
 	fstype_option=""
 	fstype=${OCF_RESKEY_fstype}
 	case "$fstype" in
 	""|"[ 	]*")
 		fstype=""
 		;;
 	*)	# found it
 		fstype_option="-t $fstype"
 		;;
 	esac
 
 	#
 	# Get the mount options, if they exist.
 	#
 	mount_options=""
 	opts=${OCF_RESKEY_options}
 	case "$opts" in
 	""|"[ 	]*")
 		opts=""
 		;;
 	*)	# found it
 		mount_options="-o $opts"
 		;;
 	esac
 
 	#
 	# Mount the device
 	#
 	ocf_log info "mounting $dev on $mp"
 	ocf_log err "mount $fstype_option $mount_options $dev $mp"
 	mount $fstype_option $mount_options "$dev" "$mp"
 	ret_val=$?
 	if [ $ret_val -ne 0 ]; then
 		ocf_log err "\
 'mount $fstype_option $mount_options $dev $mp' failed, error=$ret_val"
 		return 1
 	fi
 
 	return 0
 }
 
 
 # Agent-specific actions to take after mounting
 # (if required).
 do_post_mount() {
 	return 0
 }
 
 
 # Agent-specific actions to take before unmounting
 # (if required)
 do_pre_unmount() {
 	return 0
 }
 
 
 # Agent-specific actions to take after umount succeeds
 # (if required)
 do_post_unmount() {
 	return 0
 }
 
 
 # Agent-specific force unmount logic, if required
 # return = nonzero if successful, or 0 if unsuccessful
 # (unsuccessful = try harder)
 do_force_unmount() {
 	return 1
 }
 
 
 #
 # start_filesystem
 #
 start_filesystem() {
 	declare -i ret_val=$OCF_SUCCESS
 	declare mp="${OCF_RESKEY_mountpoint}"
 	declare dev=""			# device
 	declare fstype=""
 	declare opts=""
 	declare mount_options=""
 
 	#
 	# Check if mount point was specified.  If not, no need to continue.
 	#
 	case "$mp" in
 	""|"[ 	]*")		# nothing to mount
 		return $OCF_SUCCESS
 		;;
 	/*)			# found it
 		;;
 	*)			# invalid format
 			ocf_log err \
 "start_filesystem: Invalid mount point format (must begin with a '/'): \'$mp\'"
 		return $OCF_ERR_ARGS
 		;;
 	esac
 
 	#
 	# Get the device
 	#
 	real_device "$OCF_RESKEY_device"
 	dev="$REAL_DEVICE"
 	if [ -z "$dev" ]; then
 			ocf_log err "\
 start_filesystem: Could not match $OCF_RESKEY_device with a real device"
 			return $OCF_ERR_ARGS
 	fi
 
 	#
 	# Ensure we've got a valid directory
 	#
 	if [ -e "$mp" ]; then
 		if ! [ -d "$mp" ]; then
 			ocf_log err"\
 start_filesystem: Mount point $mp exists but is not a directory"
 			return $OCF_ERR_ARGS
 		fi
 	else
 		ocf_log err "\
 start_filesystem: Creating mount point $mp for device $dev"
 		mkdir -p "$mp"
 		ret_val=$?
 		if [ $ret_val -ne 0 ]; then
 			ocf_log err "\
 start_filesystem: Unable to create $mp.  Error code: $ret_val"
 			return $OCF_ERR_GENERIC
 		fi
 	fi
 
 	#
 	# See if the device is already mounted.
 	#
 	is_mounted "$dev" "$mp"
 	case $? in
 	$YES)		# already mounted
 		ocf_log debug "$dev already mounted"
 		return $OCF_SUCCESS
 		;;
 	$NO)		# not mounted, continue
 		;;
 	*)
 		return $FAIL
 		;;
 	esac
 
 
 	#
 	# Make sure that neither the device nor the mount point are mounted
 	# (i.e. they may be mounted in a different location).  The'mount_in_use'
 	# function checks to see if either the device or mount point are in
 	# use somewhere else on the system.
 	#
 	mount_in_use "$dev" "$mp"
 	case $? in
 	$YES)		# uh oh, someone is using the device or mount point
 		ocf_log err "\
 Cannot mount $dev on $mp, the device or mount point is already in use!"
 		return $FAIL
 		;;
 	$NO)		# good, no one else is using it
 		;;
 	$FAIL)
 		return $FAIL
 		;;
 	*)
 		ocf_log err "Unknown return from mount_in_use"
 		return $FAIL
 		;;
 	esac
 
 	do_pre_mount
 	case $? in
 	0)
 		;;
 	1)
 		return $OCF_ERR_GENERIC
 		;;
 	2)
 		return $OCF_SUCCESS
 		;;
 	esac
 
 	do_mount "$dev" "$mp"
 	case $? in
 	0)
 		;;
 	1)
 		return $OCF_ERR_GENERIC
 		;;
 	2)
 		return $OCF_SUCCESS
 		;;
 	esac
 
 	do_post_mount
 	case $? in
 	0)
 		;;
 	1)
 		return $OCF_ERR_GENERIC
 		;;
 	2)
 		return $OCF_SUCCESS
 		;;
 	esac
 
 	enable_fs_quotas "$opts" "$mp"
 
 	return $OCF_SUCCESS
 }
 
 
 #
 # stop_filesystem - unmount a file system; calls out to
 #
 stop_filesystem() {
 	declare -i ret_val=0
 	declare -i try
 	declare -i sleep_time=5		# time between each umount failure
 	declare umount_failed=""
 	declare force_umount=""
 	declare self_fence=""
 	declare quotaopts=""
 
 	#
 	# Get the mount point, if it exists.  If not, no need to continue.
 	#
 	mp=${OCF_RESKEY_mountpoint}
 	case "$mp" in
 	""|"[ 	]*")		# nothing to mount
 		return $OCF_SUCCESS
 		;;
 	/*)			# found it
 		;;
 	*)		# invalid format
 			ocf_log err \
 "stop_filesystem: Invalid mount point format (must begin with a '/'): \'$mp\'"
 		return $FAIL
 		;;
 	esac
 
 	#
 	# Get the device
 	#
 	real_device "$OCF_RESKEY_device"
 	dev="$REAL_DEVICE"
 	if [ -z "$dev" ]; then
 			ocf_log err "\
 stop: Could not match $OCF_RESKEY_device with a real device"
 			return $OCF_ERR_INSTALLED
 	fi
 
 	#
 	# Get the force unmount setting if there is a mount point.
 	#
 	case ${OCF_RESKEY_force_unmount} in
         $YES_STR)	force_umount=$YES ;;
 	on)		force_umount=$YES ;;
 	true)		force_umount=$YES ;;
 	1)		force_umount=$YES ;;
         *)		force_umount="" ;;
 	esac
 
+	#
+	# self_fence _MUST_ be initialized before calling do_pre_unmount
+	# The netfs agent depends on the self_fence variable.
+	#
 	case ${OCF_RESKEY_self_fence} in
         $YES_STR)	self_fence=$YES ;;
 	on)		self_fence=$YES ;;
 	true)		self_fence=$YES ;;
 	1)		self_fence=$YES ;;
         *)		self_fence="" ;;
 	esac
 
 	do_pre_unmount
 	case $? in
 	0)
 		;;
 	1)
 		return $OCF_ERR_GENERIC
 		;;
 	2)
 		return $OCF_SUCCESS
 		;;
 	esac
 
 	#
 	# Preparations: sync, turn off quotas
 	#
 	sync
 
 	quotaopts=$(quota_opts $OCF_RESKEY_options)
 	if [ -n "$quotaopts" ]; then
 		ocf_log debug "Turning off quotas for $mp"
 		quotaoff -$quotaopts "$mp" &> /dev/null
 	fi
 
 	#
 	# Unmount the device.
 	#
 	for try in 1 2 3; do
 		if [ $try -ne 1 ]; then
 			sleep $sleep_time
 		fi
 
 		is_mounted "$dev" "$mp"
 		case $? in
 		$NO)
 			ocf_log info "$dev is not mounted"
 			umount_failed=
 			break
 			;;
 		$YES)	# fallthrough
 			;;
 		*)
 			return $FAIL
 			;;
 		esac
 
 		case ${OCF_RESKEY_no_unmount} in
 			yes|YES|true|TRUE|YES|on|ON|1)
 				ocf_log debug "Skipping umount on stop because of 'no_unmount' option"
 				return $OCF_SUCCESS
 				;;
 			*) : ;;
 		esac
 
 		ocf_log info "unmounting $mp"
 		umount "$mp"
 		ret_val=$?
 		# some versions of umount will exit with status 16 iff
 		# the umount(2) succeeded but /etc/mtab could not be written.
 		if  [ $ret_val -eq 0 -o $ret_val -eq 16 ]; then
 			umount_failed=
 			break
 		fi
 
 		ocf_log debug "umount failed: $ret_val"
 		umount_failed=yes
 
 		if [ -z "$force_umount" ]; then
 			continue
 		fi
 
 		# Force unmount: try #1: send SIGTERM
 		if [ $try -eq 1 ]; then
 			# Try fs-specific force unmount, if provided
 			do_force_unmount
 			if [ $? -eq 0 ]; then
 				# if this succeeds, we should be done
 				continue
 			fi
 
 			ocf_log warning "Sending SIGTERM to processes on $mp"
 			kill_procs_using_mount "$mp" "TERM"
 			continue
 		else
 			ocf_log warning "Sending SIGKILL to processes on $mp"
 			kill_procs_using_mount "$mp"
 
 			if [ $? -eq 0 ]; then
 				# someone is still accessing the mount, We've already sent
 				# SIGTERM, now we've sent SIGKILL and are trying umount again.
 				continue
 			fi
 			# mount has failed, and no one is accessing it.  There's
 			# nothing left for us to try.
 			break
 		fi
 	done # for
 
 	do_post_unmount
 	case $? in
 	0)
 		;;
 	1)
 		return $OCF_ERR_GENERIC
 		;;
 	2)
 		return $OCF_SUCCESS
 		;;
 	esac
 
 	if [ -n "$umount_failed" ]; then
 		ocf_log err "'umount $mp' failed, error=$ret_val"
 
 		if [ "$self_fence" ]; then
 			ocf_log alert "umount failed - REBOOTING"
 			sync
 			reboot -fn
 		fi
 		return $OCF_ERR_GENERIC
 	fi
 
 	return $OCF_SUCCESS
 }
 
 
 do_start() {
 	declare tries=0
 	declare rv
 
 	while [ $tries -lt 3 ]; do
 		start_filesystem
 		rv=$?
 		if [ $rv -eq 0 ]; then
 			return 0
 		fi
 
 		((tries++))
 		sleep 3
 	done
 	return $rv
 }
 
 
 do_stop() {
 	stop_filesystem
 	return $?
 }
 
 
 do_monitor() {
 	ocf_log debug "Checking fs \"$OCF_RESKEY_name\", Level $OCF_CHECK_LEVEL"
 
 	#
 	# Get the device
 	#
 	real_device "$OCF_RESKEY_device"
 	dev="$REAL_DEVICE"
 	if [ -z "$dev" ]; then
 			ocf_log err "\
 start_filesystem: Could not match $OCF_RESKEY_device with a real device"
 			return $OCF_NOT_RUNNING
 	fi
 
 	is_mounted "$dev" "${OCF_RESKEY_mountpoint}"
 
 	if [ $? -ne $YES ]; then
 		ocf_log err "${OCF_RESOURCE_INSTANCE}: ${OCF_RESKEY_device} is not mounted on ${OCF_RESKEY_mountpoint}"
 		return $OCF_NOT_RUNNING
 	fi
 
 	if [ "$OCF_RESKEY_quick_status" = "1" ]; then
 		return 0
 	fi
 
 	is_alive "${OCF_RESKEY_mountpoint}"
 	[ $? -eq $YES ] && return 0
 
 	ocf_log err "fs:${OCF_RESKEY_name}: Mount point is not accessible!"
 	return $OCF_ERR_GENERIC
 }
 
 
 do_restart() {
 	stop_filesystem
 	if [ $? -ne 0 ]; then
 		return $OCF_ERR_GENERIC
 	fi
 
 	start_filesystem
 	if [ $? -ne 0 ]; then
 		return $OCF_ERR_GENERIC
 	fi
 
 	return 0
 }
 
 
 # MUST BE OVERRIDDEN
 do_metadata() {
 	return 1
 }
 
 
 do_validate() {
 	return 1
 }
 
 
 main() {
 	case $1 in
 	start)
 		do_start
 		exit $?
 		;;
 	stop)
 		do_stop
 		exit $?
 		;;
 	status|monitor)
 		do_monitor
 		exit $?
 		;;
 	restart)
 		do_restart
 		exit $?
 		;;
 	meta-data)
 		do_metadata
 		exit $?
 		;;
 	validate-all)
 		do_validate
 		;;
 	*)
 		echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
 		exit $OCF_ERR_UNIMPLEMENTED
 		;;
 	esac
 	exit 0
 }