Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Feb 2012 04:52:39 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r231993 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient
Message-ID:  <201202220452.q1M4qd6W035189@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Wed Feb 22 04:52:38 2012
New Revision: 231993
URL: http://svn.freebsd.org/changeset/base/231993

Log:
  Restructure the nfsclds structure which holds NFSv4.1 sessions so
  that it becomes a list off of the mount point. This is needed so
  that it can be easily searched for the "same server" as the DS
  just connected to. In turn, this is needed, since you cannot
  create a second session on the same server unless you have the
  record with the sequence# for the first session. The code currently
  will simply reuse the session that is already established.
  The nfscl_sameserver() is currently a stub that needs to be
  coded. This code has done a trivial file read through the DS
  provided by a Linux pNFS single server, but still needs a lot
  of work.

Modified:
  projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c
  projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c
  projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h
  projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h
  projects/nfsv4.1-client/sys/fs/nfs/nfsport.h
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clcomsubs.c
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clvfsops.c
  projects/nfsv4.1-client/sys/fs/nfsclient/nfsmount.h

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c	Wed Feb 22 04:52:38 2012	(r231993)
@@ -799,7 +799,7 @@ tryagain:
 	if (nd->nd_procnum != NFSPROC_NULL) {
 		/* If sep == NULL, set it to the default in nmp. */
 		if (sep == NULL && nmp != NULL)
-			sep = &nmp->nm_sess;
+			sep = NFSMNT_MDSSESSION(nmp);
 		/*
 		 * and now the actual NFS xdr.
 		 */

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c	Wed Feb 22 04:52:38 2012	(r231993)
@@ -107,6 +107,8 @@ MALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD r
 MALLOC_DEFINE(M_NEWNFSLAYOUT, "NFSCL layout", "NFSv4.1 Layout");
 MALLOC_DEFINE(M_NEWNFSFLAYOUT, "NFSCL flayout", "NFSv4.1 File Layout");
 MALLOC_DEFINE(M_NEWNFSDEVINFO, "NFSCL devinfo", "NFSv4.1 Device Info");
+MALLOC_DEFINE(M_NEWNFSSOCKREQ, "NFSCL sockreq", "NFS Sock Req");
+MALLOC_DEFINE(M_NEWNFSCLDS, "NFSCL session", "NFSv4.1 Session");
 
 /*
  * Definition of mutex locks.

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Wed Feb 22 04:52:38 2012	(r231993)
@@ -437,7 +437,8 @@ int nfsrpc_delegreturn(struct nfscldeleg
 int nfsrpc_getacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *, void *);
 int nfsrpc_setacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *, void *);
 int nfsrpc_exchangeid(struct nfsmount *, struct nfsclclient *,
-    struct nfsclsession *, uint32_t, struct ucred *, NFSPROC_T *);
+    struct nfssockreq *, uint32_t, struct nfsclds **, struct ucred *,
+    NFSPROC_T *);
 int nfsrpc_createsession(struct nfsmount *, struct nfsclsession *,
     struct ucred *, NFSPROC_T *);
 int nfsrpc_destroysession(struct nfsmount *, struct nfsclclient *,
@@ -457,6 +458,7 @@ int nfsrpc_layoutreturn(vnode_t, int, in
 int nfsrpc_reclaimcomplete(struct nfsmount *, struct ucred *, NFSPROC_T *);
 int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t,
     struct ucred *, NFSPROC_T *);
+void nfscl_freenfsclds(struct nfsclds *);
 
 /* nfs_clstate.c */
 int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int,

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Wed Feb 22 04:52:38 2012	(r231993)
@@ -71,13 +71,17 @@ struct nfsclsession {
 
 /*
  * This structure holds the information used to access a Data Server (DS).
+ * It is malloc'd to the correct length.
  */
 struct nfsclds {
-	struct mtx		nfsclds_mtx;
-	struct nfssockreq	nfsclds_sock;
+	LIST_ENTRY(nfsclds)	nfsclds_list;
 	struct nfsclsession	nfsclds_sess;
-	int			nfsclds_haswriteverf;
+	struct mtx		nfsclds_mtx;
+	struct nfssockreq	*nfsclds_sockp;
+	uint16_t		nfsclds_haswriteverf;
+	uint16_t		nfsclds_servownlen;
 	uint8_t			nfsclds_verf[NFSX_VERF];
+	uint8_t			nfsclds_serverown[0];
 };
 
 struct nfsclclient {
@@ -268,14 +272,14 @@ struct nfscldevinfo {
 	uint32_t			nfsdi_refcnt;
 	uint16_t			nfsdi_stripecnt;
 	uint16_t			nfsdi_addrcnt;
-	struct nfsclds			nfsdi_data[1];
+	struct nfsclds			*nfsdi_data[0];
 };
 
 /* These inline functions return values from nfsdi_data[]. */
 /*
  * Return a pointer to the address at "pos".
  */
-static __inline struct nfsclds *
+static __inline struct nfsclds **
 nfsfldi_addr(struct nfscldevinfo *ndi, int pos)
 {
 

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsport.h	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsport.h	Wed Feb 22 04:52:38 2012	(r231993)
@@ -739,6 +739,8 @@ MALLOC_DECLARE(M_NEWNFSDROLLBACK);
 MALLOC_DECLARE(M_NEWNFSLAYOUT);
 MALLOC_DECLARE(M_NEWNFSFLAYOUT);
 MALLOC_DECLARE(M_NEWNFSDEVINFO);
+MALLOC_DECLARE(M_NEWNFSSOCKREQ);
+MALLOC_DECLARE(M_NEWNFSCLDS);
 #define	M_NFSRVCACHE	M_NEWNFSRVCACHE
 #define	M_NFSDCLIENT	M_NEWNFSDCLIENT
 #define	M_NFSDSTATE	M_NEWNFSDSTATE
@@ -761,6 +763,8 @@ MALLOC_DECLARE(M_NEWNFSDEVINFO);
 #define	M_NFSLAYOUT	M_NEWNFSLAYOUT
 #define	M_NFSFLAYOUT	M_NEWNFSFLAYOUT
 #define	M_NFSDEVINFO	M_NEWNFSDEVINFO
+#define	M_NFSSOCKREQ	M_NEWNFSSOCKREQ
+#define	M_NFSCLDS	M_NEWNFSCLDS
 
 #define	NFSINT_SIGMASK(set) 						\
 	(SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) ||	\

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clcomsubs.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clcomsubs.c	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clcomsubs.c	Wed Feb 22 04:52:38 2012	(r231993)
@@ -200,7 +200,7 @@ nfscl_reqstart(struct nfsrv_descript *nd
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_SEQUENCE);
 			if (sep == NULL)
-				nfsv4_setsequence(nd, &nmp->nm_sess,
+				nfsv4_setsequence(nd, NFSMNT_MDSSESSION(nmp),
 				    nfs_bigreply[procnum]);
 			else
 				nfsv4_setsequence(nd, sep,

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Wed Feb 22 04:52:38 2012	(r231993)
@@ -87,8 +87,8 @@ static int nfsrpc_setaclrpc(vnode_t, str
     struct acl *, nfsv4stateid_t *, void *);
 static int nfsrpc_getlayout(struct nfsmount *, struct nfsfh *, int, uint32_t *,
     nfsv4stateid_t *, struct ucred *, NFSPROC_T *);
-static int nfsrpc_fillsa(struct nfsmount *, struct nfsclds *,
-    struct sockaddr_storage *, NFSPROC_T *);
+static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_storage *,
+    struct nfsclds **, NFSPROC_T *);
 static void nfscl_initsessionslots(struct nfsclsession *);
 static int nfscl_findlayoutforio(struct nfscllayout *, uint64_t, uint32_t,
     struct nfsclflayout **);
@@ -101,6 +101,7 @@ static int nfsrpc_readds(vnode_t, struct
 static int nfsrpc_writeds(vnode_t, struct uio *, int *, int *,
     nfsv4stateid_t *, struct nfsclds *, uint64_t, int,
     struct nfsfh *, int, struct ucred *, NFSPROC_T *);
+static struct nfsclds *nfscl_getsameserver(struct nfsmount *, struct nfsclds *);
 
 /*
  * nfs null call from vfs.
@@ -381,8 +382,8 @@ nfsrpc_openrpc(struct nfsmount *nmp, vno
 	*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
 	*tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
 	*tl++ = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
-	*tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-	*tl = nmp->nm_sess.nfsess_clientid.lval[1];
+	*tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+	*tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	(void) nfsm_strtom(nd, op->nfso_own->nfsow_owner, NFSV4CL_LOCKNAMELEN);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE);
@@ -806,18 +807,27 @@ nfsrpc_setclient(struct nfsmount *nmp, s
 	nfsquad_t confirm;
 	u_int32_t lease;
 	static u_int32_t rev = 0;
+	struct nfsclds *dsp;
 
 	if (nfsboottime.tv_sec == 0)
 		NFSSETBOOTTIME(nfsboottime);
 	clp->nfsc_rev = rev++;
 	if (NFSHASNFSV4N(nmp)) {
-		error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sess,
-		    NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, cred, p);
+		error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sockreq,
+		    NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, &dsp, cred, p);
 if (error) printf("exch=%d\n",error);
 		if (error == 0) {
-			nfscl_initsessionslots(&nmp->nm_sess);
-			error = nfsrpc_createsession(nmp, &nmp->nm_sess, cred,
-			    p);
+			error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
+			    cred, p);
+			if (error == 0) {
+				KASSERT(LIST_FIRST(&nmp->nm_sess) == NULL,
+				    ("nfscl session non-NULL"));
+				NFSLOCKMNT(nmp);
+				LIST_INSERT_HEAD(&nmp->nm_sess, dsp,
+				    nfsclds_list);
+				NFSUNLOCKMNT(nmp);
+			} else
+				nfscl_freenfsclds(dsp);
 if (error) printf("aft crs=%d\n",error);
 		}
 		if (error == 0 && reclaim == 0) {
@@ -888,8 +898,8 @@ if (error) printf("aft reclcom=%d\n",err
 		return (error);
 	if (nd->nd_repstat == 0) {
 	    NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
-	    nmp->nm_sess.nfsess_clientid.lval[0] = *tl++;
-	    nmp->nm_sess.nfsess_clientid.lval[1] = *tl++;
+	    NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0] = *tl++;
+	    NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1] = *tl++;
 	    confirm.lval[0] = *tl++;
 	    confirm.lval[1] = *tl;
 	    mbuf_freem(nd->nd_mrep);
@@ -901,8 +911,8 @@ if (error) printf("aft reclcom=%d\n",err
 	    nfscl_reqstart(nd, NFSPROC_SETCLIENTIDCFRM, nmp, NULL, 0, NULL,
 		NULL);
 	    NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
-	    *tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-	    *tl++ = nmp->nm_sess.nfsess_clientid.lval[1];
+	    *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+	    *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	    *tl++ = confirm.lval[0];
 	    *tl = confirm.lval[1];
 	    nd->nd_flag |= ND_USEGSSNAME;
@@ -1925,8 +1935,8 @@ nfsrpc_createv4(vnode_t dvp, char *name,
 	*tl++ = txdr_unsigned(NFSV4OPEN_ACCESSWRITE |
 	    NFSV4OPEN_ACCESSREAD);
 	*tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE);
-	*tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-	*tl = nmp->nm_sess.nfsess_clientid.lval[1];
+	*tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+	*tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	(void) nfsm_strtom(nd, owp->nfsow_owner, NFSV4CL_LOCKNAMELEN);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OPEN_CREATE);
@@ -3718,8 +3728,8 @@ nfsrpc_lockt(struct nfsrv_descript *nd, 
 	tl += 2;
 	txdr_hyper(len, tl);
 	tl += 2;
-	*tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-	*tl = nmp->nm_sess.nfsess_clientid.lval[1];
+	*tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+	*tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	nfscl_filllockowner(id, own, flags);
 	np = VTONFS(vp);
 	NFSBCOPY(np->n_fhp->nfh_fh, &own[NFSV4CL_LOCKNAMELEN],
@@ -3849,8 +3859,8 @@ nfsrpc_lock(struct nfsrv_descript *nd, s
 	    *tl++ = lp->nfsl_open->nfso_stateid.other[1];
 	    *tl++ = lp->nfsl_open->nfso_stateid.other[2];
 	    *tl++ = txdr_unsigned(lp->nfsl_seqid);
-	    *tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-	    *tl = nmp->nm_sess.nfsess_clientid.lval[1];
+	    *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+	    *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	    NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
 	    NFSBCOPY(nfhp, &own[NFSV4CL_LOCKNAMELEN], fhlen);
 	    (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
@@ -4095,8 +4105,8 @@ nfsrpc_renew(struct nfsclclient *clp, st
 	if (!NFSHASNFSV4N(nmp)) {
 		/* NFSv4.1 just uses a Sequence Op and not a Renew. */
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
-		*tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-		*tl = nmp->nm_sess.nfsess_clientid.lval[1];
+		*tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+		*tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	}
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
@@ -4129,8 +4139,8 @@ nfsrpc_rellockown(struct nfsmount *nmp, 
 		nfscl_reqstart(nd, NFSPROC_RELEASELCKOWN, nmp, NULL, 0, NULL,
 		    NULL);
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
-		*tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-		*tl = nmp->nm_sess.nfsess_clientid.lval[1];
+		*tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+		*tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 		NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
 		NFSBCOPY(fh, &own[NFSV4CL_LOCKNAMELEN], fhlen);
 		(void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
@@ -4323,22 +4333,24 @@ nfsrpc_setaclrpc(vnode_t vp, struct ucre
  */
 int
 nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclclient *clp,
-    struct nfsclsession *sep, uint32_t exchflags, struct ucred *cred,
-    NFSPROC_T *p)
+    struct nfssockreq *nrp, uint32_t exchflags, struct nfsclds **dspp,
+    struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl, v41flags;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
+	struct nfsclds *dsp;
 	struct timespec verstime;
-	int error;
+	int error, len;
 
+	*dspp = NULL;
 	nfscl_reqstart(nd, NFSPROC_EXCHANGEID, nmp, NULL, 0, NULL, NULL);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(nfsboottime.tv_sec);	/* Client owner */
 	*tl = txdr_unsigned(clp->nfsc_rev);
 	(void) nfsm_strtom(nd, clp->nfsc_id, clp->nfsc_idlen);
 
-	NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+	NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(exchflags);
 	*tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE);
 
@@ -4346,21 +4358,31 @@ nfsrpc_exchangeid(struct nfsmount *nmp, 
 	*tl = txdr_unsigned(1);
 	(void) nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
 	(void) nfsm_strtom(nd, version, strlen(version));
-	NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
+	NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
 	verstime.tv_sec = 1293840000;		/* Jan 1, 2011 */
 	verstime.tv_nsec = 0;
 	txdr_nfsv4time(&verstime, tl);
 	nd->nd_flag |= ND_USEGSSNAME;
-	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
+	error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 printf("exch err=%d reps=%d\n",error,nd->nd_repstat);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
-		NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
-		sep->nfsess_clientid.lval[0] = *tl++;
-		sep->nfsess_clientid.lval[1] = *tl++;
-		sep->nfsess_sequenceid = fxdr_unsigned(uint32_t, *tl++);
+		NFSM_DISSECT(tl, uint32_t *, 6 * NFSX_UNSIGNED + NFSX_HYPER);
+		len = fxdr_unsigned(int, *(tl + 7));
+printf("servlen=%d\n", len);
+		if (len < 1 || len > NFSV4_OPAQUELIMIT) {
+			error = NFSERR_BADXDR;
+			goto nfsmout;
+		}
+		dsp = malloc(sizeof(struct nfsclds) + len, M_NFSCLDS,
+		    M_WAITOK | M_ZERO);
+		dsp->nfsclds_servownlen = len;
+		dsp->nfsclds_sess.nfsess_clientid.lval[0] = *tl++;
+		dsp->nfsclds_sess.nfsess_clientid.lval[1] = *tl++;
+		dsp->nfsclds_sess.nfsess_sequenceid =
+		    fxdr_unsigned(uint32_t, *tl++);
 		v41flags = fxdr_unsigned(uint32_t, *tl);
 printf("v41fl=0x%x\n", v41flags);
 		if ((v41flags & NFSV4EXCH_USEPNFSMDS) != 0) {
@@ -4368,6 +4390,15 @@ printf("v41fl=0x%x\n", v41flags);
 			nmp->nm_state |= NFSSTA_PNFS;
 			NFSUNLOCKMNT(nmp);
 		}
+		nd->nd_repstat = nfsrv_mtostr(nd, dsp->nfsclds_serverown, len);
+		if (nd->nd_repstat == 0) {
+			mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
+			mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession",
+			    NULL, MTX_DEF);
+			nfscl_initsessionslots(&dsp->nfsclds_sess);
+			*dspp = dsp;
+		} else
+			free(dsp, M_NFSCLDS);
 	}
 	error = nd->nd_repstat;
 nfsmout:
@@ -4483,7 +4514,7 @@ nfsrpc_destroysession(struct nfsmount *n
 
 	nfscl_reqstart(nd, NFSPROC_DESTROYSESSION, nmp, NULL, 0, NULL, NULL);
 	NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
-	bcopy(nmp->nm_sess.nfsess_sessionid, tl, NFSX_V4SESSIONID);
+	bcopy(NFSMNT_MDSSESSION(nmp)->nfsess_sessionid, tl, NFSX_V4SESSIONID);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
@@ -4508,8 +4539,8 @@ nfsrpc_destroyclient(struct nfsmount *nm
 
 	nfscl_reqstart(nd, NFSPROC_DESTROYCLIENT, nmp, NULL, 0, NULL, NULL);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
-	*tl++ = nmp->nm_sess.nfsess_clientid.lval[0];
-	*tl = nmp->nm_sess.nfsess_clientid.lval[1];
+	*tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
+	*tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
@@ -4679,7 +4710,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct sockaddr_storage ss;
-	struct nfsclds *sa;
+	struct nfsclds *dsp = NULL, **dspp;
 	struct nfscldevinfo *ndi;
 	int addrcnt, bitcnt, error, i, isudp, j, pos, safilled, stripecnt;
 	uint8_t stripeindex;
@@ -4708,6 +4739,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		if (layouttype != fxdr_unsigned(int, *tl++))
 			printf("EEK! devinfo layout type not same!\n");
 		stripecnt = fxdr_unsigned(int, *++tl);
+printf("stripecnt=%d\n", stripecnt);
 		if (stripecnt < 1 || stripecnt > 4096) {
 			printf("NFS devinfo stripecnt %d: out of range\n",
 			    stripecnt);
@@ -4716,6 +4748,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		}
 		NFSM_DISSECT(tl, uint32_t *, (stripecnt + 1) * NFSX_UNSIGNED);
 		addrcnt = fxdr_unsigned(int, *(tl + stripecnt));
+printf("addrcnt=%d\n", addrcnt);
 		if (addrcnt < 1 || addrcnt > 128) {
 			printf("NFS devinfo addrcnt %d: out of range\n",
 			    addrcnt);
@@ -4727,9 +4760,11 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		 * Now we know how many stripe indices and addresses, so
 		 * we can allocate the structure the correct size.
 		 */
-		i = stripecnt / sizeof(struct nfsclds) + 1;
-		ndi = malloc(sizeof(*ndi) + (addrcnt + i - 1) *
-		    sizeof(struct nfsclds), M_NFSDEVINFO, M_WAITOK | M_ZERO);
+		i = (stripecnt * sizeof(uint8_t)) / sizeof(struct nfsclds *)
+		    + 1;
+printf("i=%d\n", i);
+		ndi = malloc(sizeof(*ndi) + (addrcnt + i) *
+		    sizeof(struct nfsclds *), M_NFSDEVINFO, M_WAITOK | M_ZERO);
 		NFSBCOPY(deviceid, ndi->nfsdi_deviceid, NFSX_V4DEVICEID);
 		ndi->nfsdi_refcnt = 0;
 		ndi->nfsdi_stripecnt = stripecnt;
@@ -4737,6 +4772,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		/* Fill in the stripe indices. */
 		for (i = 0; i < stripecnt; i++) {
 			stripeindex = fxdr_unsigned(uint8_t, *tl++);
+printf("stripeind=%d\n", stripeindex);
 			if (stripeindex >= addrcnt) {
 				printf("NFS devinfo stripeindex %d: too big\n",
 				    (int)stripeindex);
@@ -4756,9 +4792,10 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
-			sa = nfsfldi_addr(ndi, i);
+			dspp = nfsfldi_addr(ndi, i);
 			pos = arc4random() % cnt;	/* Choose one. */
 			safilled = 0;
+printf("dspp=%p pos=%d\n", dspp, pos);
 			for (j = 0; j < cnt; j++) {
 				error = nfsv4_getipaddr(nd, &ss, &isudp);
 				if (error != 0 && error != EPERM) {
@@ -4782,9 +4819,11 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 					      nmp->nm_nam->sa_family)) ||
 					    (safilled == 1 && ss.ss_family ==
 					     nmp->nm_nam->sa_family)) {
-						error = nfsrpc_fillsa(nmp, sa,
-						    &ss, p);
+						error = nfsrpc_fillsa(nmp, &ss,
+						    &dsp, p);
 						if (error == 0) {
+							*dspp = dsp;
+printf("safill dsp=%p\n", dsp);
 							if (ss.ss_family ==
 							 nmp->nm_nam->sa_family)
 								safilled = 2;
@@ -5002,16 +5041,19 @@ nfsrpc_getlayout(struct nfsmount *nmp, s
 }
 
 /*
- * Fill in nfsclds, doing the TCP connect plus exchangeid and create session.
- * The nfsclds structure pointed to by dsp is all zero'd out.
+ * Do a TCP connection plus exchange id and create session.
+ * If successful, a "struct nfsclds" is linked into the list for the
+ * mount point and a pointer to it is returned.
  */
 static int
-nfsrpc_fillsa(struct nfsmount *nmp, struct nfsclds *dsp,
-    struct sockaddr_storage *ssp, NFSPROC_T *p)
+nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
+    struct nfsclds **dspp, NFSPROC_T *p)
 {
 	struct sockaddr_in *sad, *ssd;
 	struct sockaddr_in6 *sad6, *ssd6;
 	struct nfsclclient *clp;
+	struct nfssockreq *nrp;
+	struct nfsclds *dsp, *tdsp;
 	int error;
 
 	KASSERT(nmp->nm_sockreq.nr_cred != NULL,
@@ -5021,6 +5063,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	NFSUNLOCKCLSTATE();
 	if (clp == NULL)
 		return (EPERM);
+	nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
 	if (ssp->ss_family == AF_INET) {
 		ssd = (struct sockaddr_in *)ssp;
 		sad = malloc(sizeof(*sad), M_SONAME, M_WAITOK | M_ZERO);
@@ -5028,7 +5071,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 		sad->sin_family = AF_INET;
 		sad->sin_port = ssd->sin_port;
 		sad->sin_addr.s_addr = ssd->sin_addr.s_addr;
-		dsp->nfsclds_sock.nr_nam = (struct sockaddr *)sad;
+		nrp->nr_nam = (struct sockaddr *)sad;
 	} else if (ssp->ss_family == AF_INET6) {
 		ssd6 = (struct sockaddr_in6 *)ssp;
 		sad6 = malloc(sizeof(*sad6), M_SONAME, M_WAITOK | M_ZERO);
@@ -5037,15 +5080,15 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 		sad6->sin6_port = ssd6->sin6_port;
 		NFSBCOPY(&ssd6->sin6_addr, &sad6->sin6_addr,
 		    sizeof(struct in6_addr));
-		dsp->nfsclds_sock.nr_nam = (struct sockaddr *)sad6;
-	} else
+		nrp->nr_nam = (struct sockaddr *)sad6;
+	} else {
+		free(nrp, M_NFSSOCKREQ);
 		return (EPERM);
-	mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
-	dsp->nfsclds_sock.nr_sotype = SOCK_STREAM;
-	mtx_init(&dsp->nfsclds_sock.nr_mtx, "nfssock", NULL, MTX_DEF);
-	dsp->nfsclds_sock.nr_prog = NFS_PROG;
-	dsp->nfsclds_sock.nr_vers = NFS_VER4;
-	mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession", NULL, MTX_DEF);
+	}
+	nrp->nr_sotype = SOCK_STREAM;
+	mtx_init(&nrp->nr_mtx, "nfssock", NULL, MTX_DEF);
+	nrp->nr_prog = NFS_PROG;
+	nrp->nr_vers = NFS_VER4;
 
 	/*
 	 * Use the credentials that were used for the mount, which are
@@ -5054,26 +5097,48 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	 * necessary, since nm_sockreq.nr_cred won't be crfree()'d until
 	 * unmount, but I did it anyhow.
 	 */
-	dsp->nfsclds_sock.nr_cred = crhold(nmp->nm_sockreq.nr_cred);
-	error = newnfs_connect(nmp, &dsp->nfsclds_sock, NULL, p, 0);
+	nrp->nr_cred = crhold(nmp->nm_sockreq.nr_cred);
+	error = newnfs_connect(nmp, nrp, NULL, p, 0);
 
 	/* Now, do the exchangeid and create session. */
 	if (error == 0)
-		error = nfsrpc_exchangeid(nmp, clp, &dsp->nfsclds_sess,
-		    NFSV4EXCH_USEPNFSDS, dsp->nfsclds_sock.nr_cred, p);
+		error = nfsrpc_exchangeid(nmp, clp, nrp, NFSV4EXCH_USEPNFSDS,
+		    &dsp, nrp->nr_cred, p);
 	if (error == 0) {
-		nfscl_initsessionslots(&dsp->nfsclds_sess);
+		dsp->nfsclds_sockp = nrp;
+		tdsp = nfscl_getsameserver(nmp, dsp);
+		if (tdsp != NULL) {
+			/*
+			 * If there is already a session for this server,
+			 * use it.
+			 */
+			(void)newnfs_disconnect(nrp);
+			nfscl_freenfsclds(dsp);
+			*dspp = tdsp;
+			return (0);
+		}
 		error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
-		    dsp->nfsclds_sock.nr_cred, p);
-	}
-	if (error != 0) {
-		NFSFREECRED(dsp->nfsclds_sock.nr_cred);
-		NFSFREEMUTEX(&dsp->nfsclds_mtx);
-		NFSFREEMUTEX(&dsp->nfsclds_sock.nr_mtx);
-		NFSFREEMUTEX(&dsp->nfsclds_sess.nfsess_mtx);
-		free(dsp->nfsclds_sock.nr_nam, M_SONAME);
-		NFSBZERO(dsp, sizeof(*dsp));
+		    nrp->nr_cred, p);
+	} else {
+		NFSFREECRED(nrp->nr_cred);
+		NFSFREEMUTEX(&nrp->nr_mtx);
+		free(nrp->nr_nam, M_SONAME);
+		free(nrp, M_NFSSOCKREQ);
 	}
+	if (error == 0) {
+		/*
+		 * The first element should be the one for the MDS.
+		 */
+		NFSLOCKMNT(nmp);
+		tdsp = LIST_FIRST(&nmp->nm_sess);
+		if (tdsp == NULL)
+			LIST_INSERT_HEAD(&nmp->nm_sess, dsp, nfsclds_list);
+		else
+			LIST_INSERT_AFTER(tdsp, dsp, nfsclds_list);
+		NFSUNLOCKMNT(nmp);
+		*dspp = dsp;
+	} else if (dsp != NULL)
+		nfscl_freenfsclds(dsp);
 	return (error);
 }
 
@@ -5248,7 +5313,7 @@ nfscl_doflayoutio(vnode_t vp, struct uio
 	int commit_thru_mds, error = 0, stripe_index, stripe_pos;
 	struct nfsnode *np;
 	struct nfsfh *fhp;
-	struct nfsclds *dsp;
+	struct nfsclds **dspp;
 
 	np = VTONFS(vp);
 	rel_off = off - flp->nfsfl_patoff;
@@ -5260,7 +5325,7 @@ nfscl_doflayoutio(vnode_t vp, struct uio
 	/* Loop around, doing I/O for each stripe unit. */
 	while (len > 0 && error == 0) {
 		stripe_index = nfsfldi_stripeindex(dp, stripe_pos);
-		dsp = nfsfldi_addr(dp, stripe_index);
+		dspp = nfsfldi_addr(dp, stripe_index);
 		if (len > transfer)
 			xfer = transfer;
 		else
@@ -5290,11 +5355,11 @@ nfscl_doflayoutio(vnode_t vp, struct uio
 		else
 			commit_thru_mds = 0;
 		if (rwflag == FREAD)
-			error = nfsrpc_readds(vp, uiop, stateidp, eofp, dsp,
+			error = nfsrpc_readds(vp, uiop, stateidp, eofp, *dspp,
 			    io_off, xfer, fhp, cred, p);
 		else
 			error = nfsrpc_writeds(vp, uiop, iomode, must_commit,
-			    stateidp, dsp, io_off, xfer, fhp, commit_thru_mds,
+			    stateidp, *dspp, io_off, xfer, fhp, commit_thru_mds,
 			    cred, p);
 		if (error == 0) {
 			transfer = stripe_unit_size;
@@ -5319,6 +5384,7 @@ nfsrpc_readds(vnode_t vp, struct uio *ui
 	struct nfsrv_descript nfsd;
 	struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 	struct nfsrv_descript *nd = &nfsd;
+	struct nfssockreq *nrp;
 
 	nd->nd_mrep = NULL;
 	nfscl_reqstart(nd, NFSPROC_READ, nmp, fhp->nfh_fh, fhp->nfh_len,
@@ -5327,7 +5393,11 @@ nfsrpc_readds(vnode_t vp, struct uio *ui
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED * 3);
 	txdr_hyper(io_off, tl);
 	*(tl + 2) = txdr_unsigned(len);
-	error = newnfs_request(nd, nmp, NULL, &dsp->nfsclds_sock, vp, p, cred,
+	nrp = dsp->nfsclds_sockp;
+	if (nrp == NULL)
+		/* If NULL, use the MDS socket. */
+		nrp = &nmp->nm_sockreq;
+	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
 	if (error != 0)
 		return (error);
@@ -5359,6 +5429,7 @@ nfsrpc_writeds(vnode_t vp, struct uio *u
 	int32_t backup;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
+	struct nfssockreq *nrp;
 
 	KASSERT(uiop->uio_iovcnt == 1, ("nfs: writerpc iovcnt > 1"));
 	nd->nd_mrep = NULL;
@@ -5371,7 +5442,11 @@ nfsrpc_writeds(vnode_t vp, struct uio *u
 	*tl++ = txdr_unsigned(*iomode);
 	*tl = txdr_unsigned(len);
 	nfsm_uiombuf(nd, uiop, len);
-	error = newnfs_request(nd, nmp, NULL, &dsp->nfsclds_sock, vp, p, cred,
+	nrp = dsp->nfsclds_sockp;
+	if (nrp == NULL)
+		/* If NULL, use the MDS socket. */
+		nrp = &nmp->nm_sockreq;
+	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
 	if (error != 0)
 		return (error);
@@ -5442,3 +5517,40 @@ nfsmout:
 	return (error);
 }
 
+/*
+ * Free up the nfsclds structure.
+ */
+void
+nfscl_freenfsclds(struct nfsclds *dsp)
+{
+	int i;
+
+	if (dsp == NULL)
+		return;
+	if (dsp->nfsclds_sockp != NULL) {
+		NFSFREECRED(dsp->nfsclds_sockp->nr_cred);
+		NFSFREEMUTEX(&dsp->nfsclds_sockp->nr_mtx);
+		free(dsp->nfsclds_sockp->nr_nam, M_SONAME);
+		free(dsp->nfsclds_sockp, M_NFSSOCKREQ);
+	}
+	NFSFREEMUTEX(&dsp->nfsclds_mtx);
+	NFSFREEMUTEX(&dsp->nfsclds_sess.nfsess_mtx);
+	for (i = 0; i < NFSV4_CBSLOTS; i++) {
+		if (dsp->nfsclds_sess.nfsess_cbslots[i].nfssl_reply != NULL)
+			m_freem(
+			    dsp->nfsclds_sess.nfsess_cbslots[i].nfssl_reply);
+	}
+	free(dsp, M_NFSCLDS);
+}
+
+static struct nfsclds *
+nfscl_getsameserver(struct nfsmount *nmp, struct nfsclds *newdsp)
+{
+
+	/*
+	 * Search the list of nfsclds structures for one with the same
+	 * server.
+	 */
+	return (LIST_FIRST(&nmp->nm_sess));
+}
+

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Wed Feb 22 04:52:38 2012	(r231993)
@@ -3216,8 +3216,10 @@ printf("cbrecall\n");
 			if (error == 0)
 				error = nfsv4_seqsession(seqid, slotid,
 				    highslot,
-				    clp->nfsc_nmp->nm_sess.nfsess_cbslots, &rep,
-				    clp->nfsc_nmp->nm_sess.nfsess_backslots);
+				    NFSMNT_MDSSESSION(clp->nfsc_nmp)->
+				    nfsess_cbslots, &rep,
+				    NFSMNT_MDSSESSION(clp->nfsc_nmp)->
+				    nfsess_backslots);
 			NFSUNLOCKCLSTATE();
 			if (error == 0) {
 				gotseq_ok = 1;
@@ -3285,7 +3287,8 @@ out:
 		clp = nfscl_getclntsess(sessionid);
 		if (clp != NULL) {
 			nfsv4_seqsess_cacherep(slotid,
-			    clp->nfsc_nmp->nm_sess.nfsess_cbslots, rep);
+			    NFSMNT_MDSSESSION(clp->nfsc_nmp)->nfsess_cbslots,
+			    rep);
 			NFSUNLOCKCLSTATE();
 		} else {
 			NFSUNLOCKCLSTATE();
@@ -3347,8 +3350,8 @@ nfscl_getmnt(int minorvers, uint8_t *ses
 		if (minorvers == NFSV4_MINORVERSION) {
 			if (clp->nfsc_cbident == cbident)
 				break;
-		} else if (!NFSBCMP(clp->nfsc_nmp->nm_sess.nfsess_sessionid,
-		    sessionid, NFSX_V4SESSIONID))
+		} else if (!NFSBCMP(NFSMNT_MDSSESSION(clp->nfsc_nmp)->
+		    nfsess_sessionid, sessionid, NFSX_V4SESSIONID))
 			break;
 	}
 	if (clp == NULL) {
@@ -3389,8 +3392,8 @@ nfscl_getclntsess(uint8_t *sessionid)
 	struct nfsclclient *clp;
 
 	LIST_FOREACH(clp, &nfsclhead, nfsc_list)
-		if (!NFSBCMP(clp->nfsc_nmp->nm_sess.nfsess_sessionid, sessionid,
-		    NFSX_V4SESSIONID))
+		if (!NFSBCMP(NFSMNT_MDSSESSION(clp->nfsc_nmp)->nfsess_sessionid,
+		    sessionid, NFSX_V4SESSIONID))
 			break;
 	return (clp);
 }
@@ -4659,20 +4662,7 @@ nfscl_freeflayout(struct nfsclflayout *f
 APPLESTATIC void
 nfscl_freedevinfo(struct nfscldevinfo *dip)
 {
-	int i;
-	struct nfsclds *dsp;
 
-	for (i = 0; i < dip->nfsdi_addrcnt; i++) {
-		dsp = nfsfldi_addr(dip, i);
-		if (dsp->nfsclds_sock.nr_nam != NULL) {
-			/* All are set or none are. */
-			NFSFREECRED(dsp->nfsclds_sock.nr_cred);
-			NFSFREEMUTEX(&dsp->nfsclds_mtx);
-			NFSFREEMUTEX(&dsp->nfsclds_sock.nr_mtx);
-			NFSFREEMUTEX(&dsp->nfsclds_sess.nfsess_mtx);
-			free(dsp->nfsclds_sock.nr_nam, M_SONAME);
-		}
-	}
 	free(dip, M_NFSDEVINFO);
 }
 

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clvfsops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clvfsops.c	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clvfsops.c	Wed Feb 22 04:52:38 2012	(r231993)
@@ -1193,9 +1193,10 @@ mountnfs(struct nfs_args *argp, struct m
 {
 	struct nfsmount *nmp;
 	struct nfsnode *np;
-	int error, i, trycnt, ret;
+	int error, trycnt, ret;
 	struct nfsvattr nfsva;
 	struct nfsclclient *clp;
+	struct nfsclds *dsp, *tdsp;
 	uint32_t lease;
 	static u_int64_t clval = 0;
 
@@ -1254,7 +1255,6 @@ printf("in mnt\n");
 		}
 		nmp->nm_sockreq.nr_cred = crhold(cred);
 		mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
-		mtx_init(&nmp->nm_sess.nfsess_mtx, "nfssession", NULL, MTX_DEF);
 		mp->mnt_data = nmp;
 		nmp->nm_getinfo = nfs_getnlminfo;
 		nmp->nm_vinvalbuf = ncl_vinvalbuf;
@@ -1445,18 +1445,15 @@ bad:
 	newnfs_disconnect(&nmp->nm_sockreq);
 	crfree(nmp->nm_sockreq.nr_cred);
 	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
-	mtx_destroy(&nmp->nm_sess.nfsess_mtx);
 	mtx_destroy(&nmp->nm_mtx);
 	if (nmp->nm_clp != NULL) {
 		NFSLOCKCLSTATE();
 		LIST_REMOVE(nmp->nm_clp, nfsc_list);
 		NFSUNLOCKCLSTATE();
 		free(nmp->nm_clp, M_NFSCLCLIENT);
-		for (i = 0; i < NFSV4_CBSLOTS; i++)
-			if (nmp->nm_sess.nfsess_cbslots[i].nfssl_reply != NULL)
-				m_freem(
-				   nmp->nm_sess.nfsess_cbslots[i].nfssl_reply);
 	}
+	LIST_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
+		nfscl_freenfsclds(dsp);
 	FREE(nmp, M_NEWNFSMNT);
 	FREE(nam, M_SONAME);
 	return (error);
@@ -1470,7 +1467,8 @@ nfs_unmount(struct mount *mp, int mntfla
 {
 	struct thread *td;
 	struct nfsmount *nmp;
-	int error, flags = 0, i, trycnt = 0;
+	int error, flags = 0, trycnt = 0;
+	struct nfsclds *dsp, *tdsp;
 
 	td = curthread;
 
@@ -1511,10 +1509,8 @@ nfs_unmount(struct mount *mp, int mntfla
 
 	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
 	mtx_destroy(&nmp->nm_mtx);
-	mtx_destroy(&nmp->nm_sess.nfsess_mtx);
-	for (i = 0; i < NFSV4_CBSLOTS; i++)
-		if (nmp->nm_sess.nfsess_cbslots[i].nfssl_reply != NULL)
-			m_freem(nmp->nm_sess.nfsess_cbslots[i].nfssl_reply);
+	LIST_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
+		nfscl_freenfsclds(dsp);
 	FREE(nmp, M_NEWNFSMNT);
 out:
 	return (error);

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfsmount.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfsmount.h	Wed Feb 22 04:51:17 2012	(r231992)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfsmount.h	Wed Feb 22 04:52:38 2012	(r231993)
@@ -70,7 +70,7 @@ struct	nfsmount {
 	int	nm_negnametimeo;	/* timeout for -ve entries (sec) */
 
 	/* Newnfs additions */
-	struct	nfsclsession nm_sess;	/* Session for NFSv4.1 mount. */
+	LIST_HEAD(, nfsclds) nm_sess;	/* Session(s) for NFSv4.1. */
 	struct	nfsclclient *nm_clp;
 	uid_t	nm_uid;			/* Uid for SetClientID etc. */
 	u_int64_t nm_clval;		/* identifies which clientid */
@@ -109,6 +109,12 @@ struct	nfsmount {
  */
 #define	VFSTONFS(mp)	((struct nfsmount *)((mp)->mnt_data))
 
+/*
+ * Get a pointer to the MDS session, which is always the first element
+ * in the list.
+ */
+#define	NFSMNT_MDSSESSION(m)	(&(LIST_FIRST(&((m)->nm_sess))->nfsclds_sess))
+
 #ifndef NFS_DEFAULT_NAMETIMEO
 #define NFS_DEFAULT_NAMETIMEO		60
 #endif



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