changeset 10276:f3e12ac807fa

6833526 4-way hang in the NFSv4 client
author Pavel Filipensky <Pavel.Filipensky@Sun.COM>
date Fri, 07 Aug 2009 10:48:38 +0100
parents f0b35eb34c31
children 8c0d8d983f7d
files usr/src/uts/common/fs/nfs/nfs4_client.c usr/src/uts/common/fs/nfs/nfs4_vnops.c usr/src/uts/common/nfs/nfs4_clnt.h
diffstat 3 files changed, 14 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/nfs/nfs4_client.c	Fri Aug 07 15:32:17 2009 +0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_client.c	Fri Aug 07 10:48:38 2009 +0100
@@ -106,7 +106,6 @@
 static int	nfs4renew(nfs4_server_t *);
 static void	nfs4_attrcache_va(vnode_t *, nfs4_ga_res_t *, int);
 static void	nfs4_pgflush_thread(pgflush_t *);
-static void	flush_pages(vnode_t *, cred_t *);
 
 static boolean_t nfs4_client_cpr_callb(void *, int);
 
@@ -302,7 +301,7 @@
 	if (nfs4_has_pages(vp) && !pgflush) {
 		if (!asyncpg) {
 			(void) nfs4_waitfor_purge_complete(vp);
-			flush_pages(vp, cr);
+			nfs4_flush_pages(vp, cr);
 		} else {
 			pgflush_t *args;
 
@@ -343,8 +342,8 @@
  * ones.
  */
 
-static void
-flush_pages(vnode_t *vp, cred_t *cr)
+void
+nfs4_flush_pages(vnode_t *vp, cred_t *cr)
 {
 	int error;
 	rnode4_t *rp = VTOR4(vp);
@@ -373,7 +372,7 @@
 	rp->r_pgflush = curthread;
 	mutex_exit(&rp->r_statelock);
 
-	flush_pages(args->vp, args->cr);
+	nfs4_flush_pages(args->vp, args->cr);
 
 	mutex_enter(&rp->r_statelock);
 	rp->r_pgflush = NULL;
--- a/usr/src/uts/common/fs/nfs/nfs4_vnops.c	Fri Aug 07 15:32:17 2009 +0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_vnops.c	Fri Aug 07 10:48:38 2009 +0100
@@ -13994,6 +13994,7 @@
 	rnode4_t	*rp = VTOR4(vp);
 	int		error = *errorp;
 	nfs_argop4	*argop;
+	int	do_flush_pages = 0;
 
 	ASSERT(nfs_zone() == mi->mi_zone);
 	/*
@@ -14018,22 +14019,11 @@
 		 * work since VOP_PUTPAGE can call nfs4_commit which calls
 		 * nfs4_start_fop. We flush the pages below after calling
 		 * nfs4_end_fop above
-		 */
-		if (!error && resp && resp->status == NFS4_OK) {
-			int error;
-
-			error = VOP_PUTPAGE(vp, (u_offset_t)0,
-			    0, B_INVAL, cred, NULL);
-
-			if (error && (error == ENOSPC || error == EDQUOT)) {
-				rnode4_t *rp = VTOR4(vp);
-
-				mutex_enter(&rp->r_statelock);
-				if (!rp->r_error)
-					rp->r_error = error;
-				mutex_exit(&rp->r_statelock);
-			}
-		}
+		 * The flush of the page cache must be done after
+		 * nfs4_end_open_seqid_sync() to avoid a 4-way hang.
+		 */
+		if (!error && resp && resp->status == NFS4_OK)
+			do_flush_pages = 1;
 	}
 	if (argsp) {
 		ASSERT(argsp->array_len == 2);
@@ -14063,6 +14053,9 @@
 		open_owner_rele(oop);
 	}
 
+	if (do_flush_pages)
+		nfs4_flush_pages(vp, cred);
+
 	(void) convoff(vp, flk, whence, offset);
 
 	lm_rel_sysid(ls);
--- a/usr/src/uts/common/nfs/nfs4_clnt.h	Fri Aug 07 15:32:17 2009 +0800
+++ b/usr/src/uts/common/nfs/nfs4_clnt.h	Fri Aug 07 10:48:38 2009 +0100
@@ -1461,6 +1461,7 @@
 extern void	nfs4_invalidate_pages(vnode_t *, u_offset_t, cred_t *);
 extern void	nfs4_purge_caches(vnode_t *, int, cred_t *, int);
 extern void	nfs4_purge_stale_fh(int, vnode_t *, cred_t *);
+extern void	nfs4_flush_pages(vnode_t *vp, cred_t *cr);
 
 extern void	nfs4rename_update(vnode_t *, vnode_t *, nfs_fh4 *, char *);
 extern void	nfs4_update_paths(vnode_t *, char *, vnode_t *, char *,