summaryrefslogtreecommitdiffstats
path: root/sys/fs/nfsclient/nfs_clvfsops.c
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2013-09-01 23:02:59 +0000
committerrmacklem <rmacklem@FreeBSD.org>2013-09-01 23:02:59 +0000
commit8d06f831a7fd6d823c0aff22030a780f8b8fd05e (patch)
treed7581118dafcc5b29d5d01d4bb41cb2114a97168 /sys/fs/nfsclient/nfs_clvfsops.c
parent09ec5c277c487bd53321f3f207be7a596ea08f65 (diff)
downloadFreeBSD-src-8d06f831a7fd6d823c0aff22030a780f8b8fd05e.zip
FreeBSD-src-8d06f831a7fd6d823c0aff22030a780f8b8fd05e.tar.gz
Forced dismounts of NFS mounts can fail when thread(s) are stuck
waiting for an RPC reply from the server while holding the mount point busy (mnt_lockref incremented). This happens because dounmount() msleep()s waiting for mnt_lockref to become 0, before calling VFS_UNMOUNT(). This patch adds a new VFS operation called VFS_PURGE(), which the NFS client implements as purging RPCs in progress. Making this call before checking mnt_lockref fixes the problem, by ensuring that the VOP_xxx() calls will fail and unbusy the mount point. Reported by: sbruno Reviewed by: kib MFC after: 2 weeks
Diffstat (limited to 'sys/fs/nfsclient/nfs_clvfsops.c')
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c
index 863c418..4a180c5 100644
--- a/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -120,6 +120,7 @@ static vfs_root_t nfs_root;
static vfs_statfs_t nfs_statfs;
static vfs_sync_t nfs_sync;
static vfs_sysctl_t nfs_sysctl;
+static vfs_purge_t nfs_purge;
/*
* nfs vfs operations.
@@ -134,6 +135,7 @@ static struct vfsops nfs_vfsops = {
.vfs_uninit = ncl_uninit,
.vfs_unmount = nfs_unmount,
.vfs_sysctl = nfs_sysctl,
+ .vfs_purge = nfs_purge,
};
VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
@@ -1676,6 +1678,19 @@ nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
}
/*
+ * Purge any RPCs in progress, so that they will all return errors.
+ * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
+ * forced dismount.
+ */
+static void
+nfs_purge(struct mount *mp)
+{
+ struct nfsmount *nmp = VFSTONFS(mp);
+
+ newnfs_nmcancelreqs(nmp);
+}
+
+/*
* Extract the information needed by the nlm from the nfs vnode.
*/
static void
OpenPOWER on IntegriCloud