Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Apr 2016 01:22:05 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r298495 - in head/sys/fs: nfs nfsserver
Message-ID:  <201604230122.u3N1M5a0054841@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat Apr 23 01:22:04 2016
New Revision: 298495
URL: https://svnweb.freebsd.org/changeset/base/298495

Log:
  Fix a LOR in the NFSv4.1 server.
  
  The ordering of acquisition of the state and session mutexes was
  reversed in two cases executed when an NFSv4.1 client created/freed
  a session. Since clients will typically do this only when mounting
  and dismounting, the likelyhood of causing a deadlock was low but possible.
  This can only occur for NFSv4.1 mounts, since the others do not
  use sessions.
  This was detected while testing the pNFS server/client where the
  client crashed during dismounting.
  The patch also reorders the unlocks, although that isn't necessary
  for correct operation.
  
  MFC after:	2 weeks

Modified:
  head/sys/fs/nfs/nfsrvstate.h
  head/sys/fs/nfsserver/nfs_nfsdstate.c

Modified: head/sys/fs/nfs/nfsrvstate.h
==============================================================================
--- head/sys/fs/nfs/nfsrvstate.h	Fri Apr 22 21:43:44 2016	(r298494)
+++ head/sys/fs/nfs/nfsrvstate.h	Sat Apr 23 01:22:04 2016	(r298495)
@@ -113,7 +113,7 @@ struct nfsclient {
  * Structure for an NFSv4.1 session.
  * Locking rules for this structure.
  * To add/delete one of these structures from the lists, you must lock
- * both: NFSLOCKSESSION(session hashhead) and NFSLOCKSTATE() in that order.
+ * both: NFSLOCKSTATE() and NFSLOCKSESSION(session hashhead) in that order.
  * To traverse the lists looking for one of these, you must hold one
  * of these two locks.
  * The exception is if the thread holds the exclusive root sleep lock.

Modified: head/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdstate.c	Fri Apr 22 21:43:44 2016	(r298494)
+++ head/sys/fs/nfsserver/nfs_nfsdstate.c	Sat Apr 23 01:22:04 2016	(r298495)
@@ -624,13 +624,13 @@ nfsrv_getclient(nfsquad_t clientid, int 
 			NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid,
 			    NFSX_V4SESSIONID);
 			shp = NFSSESSIONHASH(nsep->sess_sessionid);
+			NFSLOCKSTATE();
 			NFSLOCKSESSION(shp);
 			LIST_INSERT_HEAD(&shp->list, nsep, sess_hash);
-			NFSLOCKSTATE();
 			LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list);
 			nsep->sess_clp = clp;
-			NFSUNLOCKSTATE();
 			NFSUNLOCKSESSION(shp);
+			NFSUNLOCKSTATE();
 		    }
 		}
 	} else if (clp->lc_flags & LCL_NEEDSCONFIRM) {
@@ -5923,6 +5923,7 @@ nfsrv_freesession(struct nfsdsession *se
 	struct nfssessionhash *shp;
 	int i;
 
+	NFSLOCKSTATE();
 	if (sep == NULL) {
 		shp = NFSSESSIONHASH(sessionid);
 		NFSLOCKSESSION(shp);
@@ -5932,18 +5933,17 @@ nfsrv_freesession(struct nfsdsession *se
 		NFSLOCKSESSION(shp);
 	}
 	if (sep != NULL) {
-		NFSLOCKSTATE();
 		sep->sess_refcnt--;
 		if (sep->sess_refcnt > 0) {
-			NFSUNLOCKSTATE();
 			NFSUNLOCKSESSION(shp);
+			NFSUNLOCKSTATE();
 			return (0);
 		}
 		LIST_REMOVE(sep, sess_hash);
 		LIST_REMOVE(sep, sess_list);
-		NFSUNLOCKSTATE();
 	}
 	NFSUNLOCKSESSION(shp);
+	NFSUNLOCKSTATE();
 	if (sep == NULL)
 		return (NFSERR_BADSESSION);
 	for (i = 0; i < NFSV4_SLOTS; i++)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604230122.u3N1M5a0054841>