svn commit: r236757 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient

Rick Macklem rmacklem at FreeBSD.org
Fri Jun 8 16:12:59 UTC 2012


Author: rmacklem
Date: Fri Jun  8 16:12:58 2012
New Revision: 236757
URL: http://svn.freebsd.org/changeset/base/236757

Log:
  Assored fixes found at the Ann Arbor NFSv4.1 Bakeathon
  testing event.
  - Handle LayoutCommit not supported
  - Handle 0 length server owner names in EXCHANGEID replies
  - Fix LayoutGet so that it doesn't ask for too large a layout
  - Fix LayoutGet so that it accepts RW layouts when a Read layout was requested
  - Add some code for doing Commit through the DS (not yet enabled)
  - Assorted fixes for DS sessions
    - Fix CreateSession so that it uses the correct ClientID for DS sessions
    - Add Renew support for DS sessions
    - Configure a backchannel on DS sessions
  Plus a few fixes that were simply typos/wrong arguments to functions.

Modified:
  projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c
  projects/nfsv4.1-client/sys/fs/nfs/nfs_commonsubs.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/nfs/nfsproto.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

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c	Fri Jun  8 16:12:58 2012	(r236757)
@@ -837,39 +837,13 @@ if (nmp != NULL && i == NFSV4OP_SEQUENCE
 				if (retseq != sep->nfsess_slotseq[slot])
 					printf("retseq diff 0x%x\n", retseq);
 				retval = fxdr_unsigned(uint32_t, *++tl);
-#ifdef notyet
 				if ((retval + 1) < sep->nfsess_foreslots)
 					sep->nfsess_foreslots = (retval + 1);
 				else if ((retval + 1) > sep->nfsess_foreslots)
 					sep->nfsess_foreslots = (retval < 64) ?
 					    (retval + 1) : 64;
-#else
-				/*
-				 * There seems to be some confusion with
-				 * respect to whether this value is the
-				 * largest slot number to be used, numbered
-				 * 0<->N-1 or the size of the slot table.
-				 * In other words, is it N or N-1?
-				 * For now, play it safe and assume the
-				 * worst cases of the above, such that
-				 * nfsess_foreslots might be one less than the
-				 * server specified. This is safe, whereas
-				 * setting nfsess_foreslots one greater than
-				 * the server intended could cause grief.
-				 */
-				if (retval < sep->nfsess_foreslots)
-{
-printf("foreslots shrinking %d\n", retval);
-					sep->nfsess_foreslots = retval;
-}
-				else if (retval > sep->nfsess_foreslots)
-{
-printf("foreslots growing %d\n", retval);
-					sep->nfsess_foreslots = (retval < 64) ?
-					    retval : 64;
-}
-#endif	/* notyet */
 				mtx_unlock(&sep->nfsess_mtx);
+{ static int yyuuii = 0; int yuiop; yuiop = fxdr_unsigned(int, *++tl); if (yuiop != yyuuii) { yyuuii = yuiop; printf("seqfl=0x%x\n", yuiop); } }
 
 				/* Grab the op and status for the next one. */
 				if (opcnt > 1) {

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonsubs.c	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonsubs.c	Fri Jun  8 16:12:58 2012	(r236757)
@@ -168,7 +168,7 @@ static struct nfsuserlruhead nfsuserlruh
  */
 int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
 
 /* local functions */
 static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Fri Jun  8 16:12:58 2012	(r236757)
@@ -426,7 +426,7 @@ int nfsrpc_fsinfo(vnode_t, struct nfsfsi
     NFSPROC_T *, struct nfsvattr *, int *, void *);
 int nfsrpc_pathconf(vnode_t, struct nfsv3_pathconf *,
     struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, void *);
-int nfsrpc_renew(struct nfsclclient *, struct ucred *,
+int nfsrpc_renew(struct nfsclclient *, struct nfsclds *, struct ucred *,
     NFSPROC_T *);
 int nfsrpc_rellockown(struct nfsmount *, struct nfscllockowner *, uint8_t *,
     int, struct ucred *, NFSPROC_T *);
@@ -440,13 +440,13 @@ int nfsrpc_exchangeid(struct nfsmount *,
     struct nfssockreq *, uint32_t, struct nfsclds **, struct ucred *,
     NFSPROC_T *);
 int nfsrpc_createsession(struct nfsmount *, struct nfsclsession *,
-    uint32_t, int, struct ucred *, NFSPROC_T *);
+    struct nfssockreq *, uint32_t, int, struct ucred *, NFSPROC_T *);
 int nfsrpc_destroysession(struct nfsmount *, struct nfsclclient *,
     struct ucred *, NFSPROC_T *);
 int nfsrpc_destroyclient(struct nfsmount *, struct nfsclclient *,
     struct ucred *, NFSPROC_T *);
 int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t, uint64_t,
-    uint64_t, nfsv4stateid_t *, int *, struct nfsclflayouthead *,
+    uint64_t, int, nfsv4stateid_t *, int *, struct nfsclflayouthead *,
     struct ucred *, NFSPROC_T *, void *);
 int nfsrpc_getdeviceinfo(struct nfsmount *, uint8_t *, int, uint32_t *,
     struct nfscldevinfo **, struct ucred *, NFSPROC_T *);

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Fri Jun  8 16:12:58 2012	(r236757)
@@ -60,6 +60,7 @@ struct nfsclsession {
 	uint32_t	nfsess_slotseq[64];	/* Max for 64bit nm_slots */
 	uint64_t	nfsess_slots;
 	uint32_t	nfsess_sequenceid;
+	uint32_t	nfsess_maxcache;	/* Max size for cached reply. */
 	uint16_t	nfsess_foreslots;
 	uint16_t	nfsess_backslots;
 	uint8_t		nfsess_sessionid[NFSX_V4SESSIONID];
@@ -75,6 +76,7 @@ struct nfsclds {
 	struct nfsclsession	nfsclds_sess;
 	struct mtx		nfsclds_mtx;
 	struct nfssockreq	*nfsclds_sockp;
+	time_t			nfsclds_expire;
 	uint16_t		nfsclds_flags;
 	uint16_t		nfsclds_servownlen;
 	uint8_t			nfsclds_verf[NFSX_VERF];

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsport.h	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsport.h	Fri Jun  8 16:12:58 2012	(r236757)
@@ -349,11 +349,12 @@
 #define	NFSPROC_RECLAIMCOMPL	50
 #define	NFSPROC_WRITEDS		51
 #define	NFSPROC_READDS		52
+#define	NFSPROC_COMMITDS	53
 
 /*
  * Must be defined as one higher than the last NFSv4.1 Proc# above.
  */
-#define	NFSV41_NPROCS		53
+#define	NFSV41_NPROCS		54
 
 #endif	/* NFS_V3NPROCS */
 
@@ -835,6 +836,7 @@ void newnfs_realign(struct mbuf **);
  */
 #define	NFSSTA_HASWRITEVERF	0x00040000  /* Has write verifier */
 #define	NFSSTA_GOTFSINFO	0x00100000  /* Got the fsinfo */
+#define	NFSSTA_NOLAYOUTCOMMIT	0x04000000  /* Don't do LayoutCommit */
 #define	NFSSTA_SESSPERSIST	0x08000000  /* Has a persistent session */
 #define	NFSSTA_TIMEO		0x10000000  /* Experiencing a timeout */
 #define	NFSSTA_LOCKTIMEO	0x20000000  /* Experiencing a lockd timeout */
@@ -861,6 +863,7 @@ void newnfs_realign(struct mbuf **);
 #define	NFSSETWRITEVERF(n)	((n)->nm_state |= NFSSTA_HASWRITEVERF)
 #define	NFSSETHASSETFSID(n)	((n)->nm_state |= NFSSTA_HASSETFSID)
 #define	NFSHASPNFSOPT(n)	((n)->nm_flag & NFSMNT_PNFS)
+#define	NFSHASNOLAYOUTCOMMIT(n)	((n)->nm_state & NFSSTA_NOLAYOUTCOMMIT)
 #define	NFSHASSESSPERSIST(n)	((n)->nm_state & NFSSTA_SESSPERSIST)
 #define	NFSHASPNFS(n)		((n)->nm_state & NFSSTA_PNFS)
 

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsproto.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsproto.h	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsproto.h	Fri Jun  8 16:12:58 2012	(r236757)
@@ -316,11 +316,12 @@
 #define	NFSPROC_RECLAIMCOMPL	50
 #define	NFSPROC_WRITEDS		51
 #define	NFSPROC_READDS		52
+#define	NFSPROC_COMMITDS	53
 
 /*
  * Must be defined as one higher than the last NFSv4.1 Proc# above.
  */
-#define	NFSV41_NPROCS		53
+#define	NFSV41_NPROCS		54
 
 #endif	/* NFS_V3NPROCS */
 

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clcomsubs.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clcomsubs.c	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clcomsubs.c	Fri Jun  8 16:12:58 2012	(r236757)
@@ -111,6 +111,7 @@ static struct {
 	{ NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
 	{ NFSV4OP_WRITE, 1, "WriteDS", 7, },
 	{ NFSV4OP_READ, 1, "ReadDS", 6, },
+	{ NFSV4OP_COMMIT, 1, "CommitDS", 8, },
 };
 
 /*
@@ -119,7 +120,7 @@ static struct {
 static int nfs_bigrequest[NFSV41_NPROCS] = {
 	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 1, 0
+	0, 0, 0, 0, 0, 0, 1, 0, 0
 };
 
 /*
@@ -175,10 +176,12 @@ nfscl_reqstart(struct nfsrv_descript *nd
 				 * Sequence Op.
 				 */
 				opcnt = 1;
-			else if (procnum == NFSPROC_WRITEDS)
+			else if (procnum == NFSPROC_WRITEDS ||
+			    procnum == NFSPROC_COMMITDS)
 				/*
-				 * For the special case of a Write to a DS,
-				 * the opcnt == 3, for Sequence, PutFH, Write.
+				 * For the special case of a Writeor Commit to
+				 * a DS, the opcnt == 3, for Sequence, PutFH,
+				 * Write/Commit.
 				 */
 				opcnt = 3;
 		}
@@ -211,7 +214,8 @@ nfscl_reqstart(struct nfsrv_descript *nd
 			*tl = txdr_unsigned(NFSV4OP_PUTFH);
 			(void) nfsm_fhtom(nd, nfhp, fhlen, 0);
 			if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
-			    == 2 && procnum != NFSPROC_WRITEDS) {
+			    == 2 && procnum != NFSPROC_WRITEDS &&
+			    procnum != NFSPROC_COMMITDS) {
 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 				*tl = txdr_unsigned(NFSV4OP_GETATTR);
 				NFSWCCATTR_ATTRBIT(&attrbits);

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jun  8 16:12:58 2012	(r236757)
@@ -117,6 +117,10 @@ static int nfsrpc_writeds(vnode_t, struc
     struct nfsfh *, int, struct ucred *, NFSPROC_T *);
 static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
     struct nfsclds *, struct nfsclds **);
+#ifdef notyet
+static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
+    struct nfsfh *, struct ucred *, NFSPROC_T *, void *);
+#endif
 
 /*
  * nfs null call from vfs.
@@ -816,7 +820,7 @@ nfsrpc_setclient(struct nfsmount *nmp, s
 	nfsquad_t confirm;
 	u_int32_t lease;
 	static u_int32_t rev = 0;
-	struct nfsclds *dsp;
+	struct nfsclds *dsp, *ndsp, *tdsp;
 
 	if (nfsboottime.tv_sec == 0)
 		NFSSETBOOTTIME(nfsboottime);
@@ -827,11 +831,14 @@ nfsrpc_setclient(struct nfsmount *nmp, s
 if (error) printf("exch=%d\n",error);
 		if (error == 0) {
 			error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
+			    &nmp->nm_sockreq,
 			    dsp->nfsclds_sess.nfsess_sequenceid, 1, cred, p);
 			if (error == 0) {
-				KASSERT(TAILQ_FIRST(&nmp->nm_sess) == NULL,
-				    ("nfscl session non-NULL"));
 				NFSLOCKMNT(nmp);
+				TAILQ_FOREACH_SAFE(tdsp, &nmp->nm_sess,
+				    nfsclds_list, ndsp)
+					nfscl_freenfsclds(tdsp);
+				TAILQ_INIT(&nmp->nm_sess);
 				TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp,
 				    nfsclds_list);
 				NFSUNLOCKMNT(nmp);
@@ -842,7 +849,8 @@ if (error) printf("aft crs=%d\n",error);
 		if (error == 0 && reclaim == 0) {
 			error = nfsrpc_reclaimcomplete(nmp, cred, p);
 if (error) printf("aft reclcom=%d\n",error);
-			if (error == NFSERR_COMPLETEALREADY)
+			if (error == NFSERR_COMPLETEALREADY ||
+			    error == NFSERR_NOTSUPP)
 				/* Ignore this error. */
 				error = 0;
 		}
@@ -4159,27 +4167,34 @@ nfsmout:
  * This function performs the Renew RPC.
  */
 APPLESTATIC int
-nfsrpc_renew(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p)
+nfsrpc_renew(struct nfsclclient *clp, struct nfsclds *dsp, struct ucred *cred,
+    NFSPROC_T *p)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct nfsmount *nmp;
 	int error;
+	struct nfssockreq *nrp;
 
 	nmp = clp->nfsc_nmp;
 	if (nmp == NULL)
 		return (0);
-	nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL,
+	    &dsp->nfsclds_sess);
 	if (!NFSHASNFSV4N(nmp)) {
 		/* NFSv4.1 just uses a Sequence Op and not a Renew. */
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		*tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
 		*tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
 	}
+	nrp = dsp->nfsclds_sockp;
+	if (nrp == NULL)
+		/* If NULL, use the MDS socket. */
+		nrp = &nmp->nm_sockreq;
 	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);
+	error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
+	    NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
 	if (error)
 		return (error);
 	error = nd->nd_repstat;
@@ -4441,20 +4456,24 @@ printf("exch err=%d reps=%d\n",error,nd-
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
+printf("x1\n");
 		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) {
+		if (len < 0 || len > NFSV4_OPAQUELIMIT) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		dsp = malloc(sizeof(struct nfsclds) + len, M_NFSCLDS,
 		    M_WAITOK | M_ZERO);
+		dsp->nfsclds_expire = NFSD_MONOSEC + clp->nfsc_renew;
 		dsp->nfsclds_servownlen = len;
 		dsp->nfsclds_sess.nfsess_clientid.lval[0] = *tl++;
 		dsp->nfsclds_sess.nfsess_clientid.lval[1] = *tl++;
+printf("sess 0x%x 0x%x\n",dsp->nfsclds_sess.nfsess_clientid.lval[0],dsp->nfsclds_sess.nfsess_clientid.lval[1]);
 		dsp->nfsclds_sess.nfsess_sequenceid =
 		    fxdr_unsigned(uint32_t, *tl++);
+printf("sess seq=%d\n",dsp->nfsclds_sess.nfsess_sequenceid);
 		v41flags = fxdr_unsigned(uint32_t, *tl);
 printf("v41fl=0x%x nmfl=0x%x\n", v41flags, nmp->nm_flag);
 		if ((v41flags & NFSV4EXCH_USEPNFSMDS) != 0 &&
@@ -4467,7 +4486,10 @@ printf("set PNFS\n");
 		}
 		if ((v41flags & NFSV4EXCH_USEPNFSDS) != 0)
 			dsp->nfsclds_flags |= NFSCLDS_DS;
-		nd->nd_repstat = nfsrv_mtostr(nd, dsp->nfsclds_serverown, len);
+		if (len > 0)
+			nd->nd_repstat = nfsrv_mtostr(nd,
+			    dsp->nfsclds_serverown, len);
+{ int xxxx; for (xxxx=0; xxxx < len; xxxx++) printf("0x%x ", dsp->nfsclds_serverown[xxxx]); printf("\n"); }
 		if (nd->nd_repstat == 0) {
 			mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
 			mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession",
@@ -4488,7 +4510,8 @@ nfsmout:
  */
 int
 nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,
-    uint32_t sequenceid, int mds, struct ucred *cred, NFSPROC_T *p)
+    struct nfssockreq *nrp, uint32_t sequenceid, int mds, struct ucred *cred,
+    NFSPROC_T *p)
 {
 	uint32_t crflags, *tl;
 	struct nfsrv_descript nfsd;
@@ -4499,10 +4522,11 @@ nfsrpc_createsession(struct nfsmount *nm
 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 	*tl++ = sep->nfsess_clientid.lval[0];
 	*tl++ = sep->nfsess_clientid.lval[1];
+printf("crs clid 0x%x 0x%x\n",sep->nfsess_clientid.lval[0],sep->nfsess_clientid.lval[1]);
 	*tl++ = txdr_unsigned(sequenceid);
 printf("clseq0=0x%x\n",sequenceid);
 	crflags = (NFSMNT_RDONLY(nmp->nm_mountp) ? 0 : NFSV4CRSESS_PERSIST);
-	if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0 && mds != 0)
+	if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0)
 		crflags |= NFSV4CRSESS_CONNBACKCHAN;
 	*tl = txdr_unsigned(crflags);
 
@@ -4538,8 +4562,8 @@ printf("clseq0=0x%x\n",sequenceid);
 	*tl++ = 0;				/* Gid == 0 */
 	*tl = 0;				/* No additional gids */
 	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);
+	error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred, NFS_PROG,
+	    NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
@@ -4560,7 +4584,9 @@ printf("crfl=0x%x\n",crflags);
 		/* Get the fore channel slot count. */
 		NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 printf("cr %d %d %d %d %d\n",fxdr_unsigned(uint32_t, *tl),fxdr_unsigned(uint32_t, *(tl+1)),fxdr_unsigned(uint32_t, *(tl+2)),fxdr_unsigned(uint32_t, *(tl+3)),fxdr_unsigned(uint32_t, *(tl+4)));
-		tl += 5;		/* Skip the other counts. */		
+		tl += 3;		/* Skip the other counts. */		
+		sep->nfsess_maxcache = fxdr_unsigned(int, *tl++);
+		tl++;
 		sep->nfsess_foreslots = fxdr_unsigned(uint16_t, *tl++);
 printf("fore slots=%d\n", sep->nfsess_foreslots);
 		irdcnt = fxdr_unsigned(int, *tl);
@@ -4637,19 +4663,20 @@ nfsrpc_destroyclient(struct nfsmount *nm
  */
 int
 nfsrpc_layoutget(struct nfsmount *nmp, uint8_t *fhp, int fhlen, int iomode,
-    uint64_t offset, uint64_t len, uint64_t minlen, nfsv4stateid_t *stateidp,
-    int *retonclosep, struct nfsclflayouthead *flhp, struct ucred *cred,
-    NFSPROC_T *p, void *stuff)
+    uint64_t offset, uint64_t len, uint64_t minlen, int layoutlen,
+    nfsv4stateid_t *stateidp, int *retonclosep, struct nfsclflayouthead *flhp,
+    struct ucred *cred, NFSPROC_T *p, void *stuff)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsfh *nfhp;
 	struct nfsclflayout *flp, *prevflp, *tflp;
-	int cnt, error, fhcnt, nfhlen, i, j;
+	int cnt, error, gotiomode, fhcnt, nfhlen, i, j;
 	uint8_t *cp;
 	uint64_t retlen;
 
 	flp = NULL;
+	gotiomode = -1;
 	nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL);
 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
 	    NFSX_STATEID);
@@ -4667,7 +4694,7 @@ printf("layget seq=%d\n", stateidp->seqi
 	*tl++ = stateidp->other[0];
 	*tl++ = stateidp->other[1];
 	*tl++ = stateidp->other[2];
-	*tl = txdr_unsigned(100000);	/* take a large layout list */
+	*tl = txdr_unsigned(layoutlen);
 	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);
@@ -4712,6 +4739,7 @@ printf("fhcnt=%d\n", fhcnt);
 				    M_NFSFLAYOUT, M_WAITOK);
 			flp->nfsfl_flags = 0;
 			flp->nfsfl_fhcnt = 0;
+			flp->nfsfl_devp = NULL;
 			flp->nfsfl_off = fxdr_hyper(tl); tl += 2;
 			retlen = fxdr_hyper(tl); tl += 2;
 			if (flp->nfsfl_off + retlen < flp->nfsfl_off)
@@ -4719,7 +4747,9 @@ printf("fhcnt=%d\n", fhcnt);
 			else
 				flp->nfsfl_end = flp->nfsfl_off + retlen;
 			flp->nfsfl_iomode = fxdr_unsigned(int, *tl++);
-printf("layg iom=%d\n", iomode);
+			if (gotiomode == -1)
+				gotiomode = flp->nfsfl_iomode;
+printf("layg reqiom=%d retiom=%d\n", iomode, flp->nfsfl_iomode);
 			if (fxdr_unsigned(int, *tl++) !=
 			    NFSLAYOUT_NFSV4_1_FILES) {
 				printf("NFSv4.1: got non-files layout\n");
@@ -4751,7 +4781,7 @@ printf("layg iom=%d\n", iomode);
 				NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(nfhlen));
 				NFSBCOPY(cp, nfhp->nfh_fh, nfhlen);
 			}
-			if (flp->nfsfl_iomode == iomode) {
+			if (flp->nfsfl_iomode == gotiomode) {
 				/* Keep the list in increasing offset order. */
 				tflp = LIST_FIRST(flhp);
 				prevflp = NULL;
@@ -5082,7 +5112,8 @@ nfsrpc_getlayout(struct nfsmount *nmp, v
 	struct nfsclflayout *flp;
 	struct nfscldevinfo *dip;
 	struct nfsclflayouthead flh;
-	int error = 0, recalled, retonclose;
+	int error = 0, layoutlen, recalled, retonclose;
+	nfsv4stateid_t stateid;
 
 	*lypp = NULL;
 	lyp = nfscl_getlayout(nmp->nm_clp, nfhp->nfh_fh, nfhp->nfh_len,
@@ -5091,9 +5122,16 @@ nfsrpc_getlayout(struct nfsmount *nmp, v
 		if (recalled != 0)
 			return (EIO);
 		LIST_INIT(&flh);
+		layoutlen = NFSMNT_MDSSESSION(nmp)->nfsess_maxcache -
+		    (NFSX_STATEID + 3 * NFSX_UNSIGNED);
+printf("layoutlen=%d\n", layoutlen);
+		stateid.seqid = 0;
+		stateid.other[0] = stateidp->other[0];
+		stateid.other[1] = stateidp->other[1];
+		stateid.other[2] = stateidp->other[2];
 		error = nfsrpc_layoutget(nmp, nfhp->nfh_fh, nfhp->nfh_len,
-		    iomode, (uint64_t)0, INT64_MAX, (uint64_t)0,
-		    stateidp, &retonclose, &flh, cred, p, NULL);
+		    iomode, (uint64_t)0, INT64_MAX, (uint64_t)0, layoutlen,
+		    &stateid, &retonclose, &flh, cred, p, NULL);
 		if (error == 0)
 			LIST_FOREACH(flp, &flh, nfsfl_list) {
 				error = nfscl_adddevinfo(nmp, NULL, flp);
@@ -5112,7 +5150,7 @@ nfsrpc_getlayout(struct nfsmount *nmp, v
 			}
 		if (error == 0)
 			error = nfscl_layout(nmp, vp, nfhp->nfh_fh,
-			    nfhp->nfh_len, stateidp, retonclose, &flh, &lyp,
+			    nfhp->nfh_len, &stateid, retonclose, &flh, &lyp,
 			    cred, p);
 	}
 	if (lyp != NULL) {
@@ -5138,7 +5176,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	struct nfsclclient *clp;
 	struct nfssockreq *nrp;
 	struct nfsclds *dsp, *tdsp;
-	int error, same_as_mds;
+	int error;
 	enum nfsclds_state retv;
 	uint32_t sequenceid;
 
@@ -5149,52 +5187,90 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	NFSUNLOCKCLSTATE();
 	if (clp == NULL)
 		return (EPERM);
-	same_as_mds = 0;
-	nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
 	if (ssp->ss_family == AF_INET) {
 		ssd = (struct sockaddr_in *)ssp;
+printf("ds addr=0x%x ", ssd->sin_addr.s_addr);
+		NFSLOCKMNT(nmp);
+
+		/*
+		 * Check to see if we already have a session for this
+		 * address that is usable for a DS.
+		 * Note that the MDS's address is in a different place
+		 * than the sessions already acquired for DS's.
+		 */
+		msad = (struct sockaddr_in *)nmp->nm_sockreq.nr_nam;
+if (msad != NULL) printf("maddr=0x%x", msad->sin_addr.s_addr);
+printf("\n");
+		tdsp = TAILQ_FIRST(&nmp->nm_sess);
+		while (tdsp != NULL) {
+			if (msad != NULL && msad->sin_family == AF_INET &&
+			    ssd->sin_addr.s_addr == msad->sin_addr.s_addr &&
+			    ssd->sin_port == msad->sin_port &&
+			    (tdsp->nfsclds_flags & NFSCLDS_DS) != 0) {
+				*dspp = tdsp;
+				NFSUNLOCKMNT(nmp);
+printf("fnd same addr\n");
+				return (0);
+			}
+			tdsp = TAILQ_NEXT(tdsp, nfsclds_list);
+			if (tdsp != NULL && tdsp->nfsclds_sockp != NULL)
+				msad = (struct sockaddr_in *)
+				    tdsp->nfsclds_sockp->nr_nam;
+			else
+				msad = NULL;
+		}
+		NFSUNLOCKMNT(nmp);
+
+		/* No IP address match, so look for new/trunked one. */
 		sad = malloc(sizeof(*sad), M_SONAME, M_WAITOK | M_ZERO);
 		sad->sin_len = sizeof(*sad);
 		sad->sin_family = AF_INET;
 		sad->sin_port = ssd->sin_port;
 		sad->sin_addr.s_addr = ssd->sin_addr.s_addr;
+		nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
 		nrp->nr_nam = (struct sockaddr *)sad;
-		/* Now check to see if this address is the same as the MDS. */
-		msad = (struct sockaddr_in *)nmp->nm_sockreq.nr_nam;
-		if (msad != NULL && msad->sin_family == AF_INET &&
-		    sad->sin_addr.s_addr == msad->sin_addr.s_addr &&
-		    sad->sin_port == msad->sin_port)
-			same_as_mds = 1;
 	} else if (ssp->ss_family == AF_INET6) {
 		ssd6 = (struct sockaddr_in6 *)ssp;
+		NFSLOCKMNT(nmp);
+
+		/*
+		 * Check to see if we already have a session for this
+		 * address that is usable for a DS.
+		 * Note that the MDS's address is in a different place
+		 * than the sessions already acquired for DS's.
+		 */
+		msad6 = (struct sockaddr_in6 *)nmp->nm_sockreq.nr_nam;
+		tdsp = TAILQ_FIRST(&nmp->nm_sess);
+		while (tdsp != NULL) {
+			if (msad6 != NULL && msad6->sin6_family == AF_INET6 &&
+			    IN6_ARE_ADDR_EQUAL(&ssd6->sin6_addr,
+			    &msad6->sin6_addr) &&
+			    ssd6->sin6_port == msad6->sin6_port &&
+			    (tdsp->nfsclds_flags & NFSCLDS_DS) != 0) {
+				*dspp = tdsp;
+				NFSUNLOCKMNT(nmp);
+				return (0);
+			}
+			tdsp = TAILQ_NEXT(tdsp, nfsclds_list);
+			if (tdsp != NULL && tdsp->nfsclds_sockp != NULL)
+				msad6 = (struct sockaddr_in6 *)
+				    tdsp->nfsclds_sockp->nr_nam;
+			else
+				msad6 = NULL;
+		}
+		NFSUNLOCKMNT(nmp);
+
+		/* No IP address match, so look for new/trunked one. */
 		sad6 = malloc(sizeof(*sad6), M_SONAME, M_WAITOK | M_ZERO);
 		sad6->sin6_len = sizeof(*sad6);
 		sad6->sin6_family = AF_INET6;
 		sad6->sin6_port = ssd6->sin6_port;
 		NFSBCOPY(&ssd6->sin6_addr, &sad6->sin6_addr,
 		    sizeof(struct in6_addr));
+		nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
 		nrp->nr_nam = (struct sockaddr *)sad6;
-		/* Now check to see if this address is the same as the MDS. */
-		msad6 = (struct sockaddr_in6 *)nmp->nm_sockreq.nr_nam;
-		if (msad6 != NULL && msad6->sin6_family == AF_INET6 &&
-		    IN6_ARE_ADDR_EQUAL(&sad6->sin6_addr, &msad6->sin6_addr) &&
-		    sad6->sin6_port == msad6->sin6_port)
-			same_as_mds = 1;
-	} else {
-		free(nrp, M_NFSSOCKREQ);
+	} else
 		return (EPERM);
-	}
-
-	/*
-	 * If same address as the MDS and the MDS is a DS, use the MDS session.
-	 */
-	if (same_as_mds != 0 &&
-	    (TAILQ_FIRST(&nmp->nm_sess)->nfsclds_flags & NFSCLDS_DS) != 0) {
-		free(nrp->nr_nam, M_SONAME);
-		free(nrp, M_NFSSOCKREQ);
-		*dspp = TAILQ_FIRST(&nmp->nm_sess);
-		return (0);
-	}
 
 	nrp->nr_sotype = SOCK_STREAM;
 	mtx_init(&nrp->nr_mtx, "nfssock", NULL, MTX_DEF);
@@ -5210,15 +5286,18 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	 */
 	nrp->nr_cred = crhold(nmp->nm_sockreq.nr_cred);
 	error = newnfs_connect(nmp, nrp, NULL, p, 0);
+printf("ds conn=%d\n", error);
 
 	/* Now, do the exchangeid and create session. */
 	if (error == 0)
 		error = nfsrpc_exchangeid(nmp, clp, nrp, NFSV4EXCH_USEPNFSDS,
 		    &dsp, nrp->nr_cred, p);
+printf("ds exch=%d\n", error);
 	if (error == 0) {
 		dsp->nfsclds_sockp = nrp;
 		NFSLOCKMNT(nmp);
 		retv = nfscl_getsameserver(nmp, dsp, &tdsp);
+printf("getsame ret=%d\n", retv);
 		if (retv == NFSDSP_USETHISSESSION) {
 			NFSUNLOCKMNT(nmp);
 			/*
@@ -5230,14 +5309,14 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 			*dspp = tdsp;
 			return (0);
 		}
-		if (retv == NFSDSP_SEQTHISSESSION) {
-			tdsp->nfsclds_sess.nfsess_sequenceid++;
+		if (retv == NFSDSP_SEQTHISSESSION)
 			sequenceid = tdsp->nfsclds_sess.nfsess_sequenceid;
-		} else
+		else
 			sequenceid = dsp->nfsclds_sess.nfsess_sequenceid;
 		NFSUNLOCKMNT(nmp);
 		error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
-		    sequenceid, 0, nrp->nr_cred, p);
+		    nrp, sequenceid, 0, nrp->nr_cred, p);
+printf("dscrsess=%d\n", error);
 	} else {
 		NFSFREECRED(nrp->nr_cred);
 		NFSFREEMUTEX(&nrp->nr_mtx);
@@ -5245,6 +5324,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 		free(nrp, M_NFSSOCKREQ);
 	}
 	if (error == 0) {
+printf("add dssess\n");
 		/*
 		 * Put it at the end of the list. That way the list
 		 * is ordered by when the entry was added. This matters
@@ -5342,7 +5422,6 @@ if (error == 2) printf("rwacc=0x%x\n", r
 	    np->n_fhp->nfh_len, &recalled);
 	if (layp == NULL) {
 		/* Try and get a Layout, if it is supported. */
-		stateid.seqid = 0;
 		if (rwaccess == NFSV4OPEN_ACCESSWRITE ||
 		    (np->n_flag & NWRITEOPENED) != 0)
 			iolaymode = NFSLAYOUTIOMODE_RW;
@@ -5710,8 +5789,9 @@ nfscl_getsameserver(struct nfsmount *nmp
 	cur_dsp = NULL;
 	TAILQ_FOREACH(dsp, &nmp->nm_sess, nfsclds_list) {
 		if (dsp->nfsclds_servownlen == newdsp->nfsclds_servownlen &&
+		    dsp->nfsclds_servownlen != 0 &&
 		    !NFSBCMP(dsp->nfsclds_serverown, newdsp->nfsclds_serverown,
-		     dsp->nfsclds_servownlen)) {
+		    dsp->nfsclds_servownlen)) {
 printf("fnd same fdsp=%p dsp=%p flg=0x%x\n", TAILQ_FIRST(&nmp->nm_sess), dsp, dsp->nfsclds_flags);
 			/* Server major id matches. */
 			if ((dsp->nfsclds_flags & NFSCLDS_DS) != 0) {
@@ -5734,3 +5814,48 @@ printf("fnd same fdsp=%p dsp=%p flg=0x%x
 	return (NFSDSP_NOTFOUND);
 }
 
+#ifdef notyet
+/*
+ * NFS commit rpc to a DS.
+ */
+static int
+nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
+    struct nfsfh *fhp, struct ucred *cred, NFSPROC_T *p, void *stuff)
+{
+	uint32_t *tl;
+	struct nfsrv_descript nfsd, *nd = &nfsd;
+	struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
+	struct nfssockreq *nrp;
+	int error;
+	
+	nfscl_reqstart(nd, NFSPROC_COMMITDS, nmp, fhp->nfh_fh, fhp->nfh_len,
+	    NULL, &dsp->nfsclds_sess);
+	NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
+	txdr_hyper(offset, tl);
+	tl += 2;
+	*tl = txdr_unsigned(cnt);
+	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)
+		return (error);
+	if (nd->nd_repstat == 0) {
+		NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
+		NFSLOCKDS(dsp);
+		if (NFSBCMP(tl, dsp->nfsclds_verf, NFSX_VERF)) {
+			NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
+			error = NFSERR_STALEWRITEVERF;
+		}
+		NFSUNLOCKDS(dsp);
+	}
+nfsmout:
+	if (error == 0 && nd->nd_repstat != 0)
+		error = nd->nd_repstat;
+	mbuf_freem(nd->nd_mrep);
+	return (error);
+}
+#endif
+

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Fri Jun  8 13:27:30 2012	(r236756)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Fri Jun  8 16:12:58 2012	(r236757)
@@ -1887,7 +1887,8 @@ nfscl_recover(struct nfsclclient *clp, s
 	struct nfsreq *rep;
 	u_int64_t len;
 	u_int32_t delegtype = NFSV4OPEN_DELEGATEWRITE, mode;
-	int igotlock = 0, error, trycnt, firstlock, s;
+	int i, igotlock = 0, error, trycnt, firstlock, s;
+	struct nfscllayout *lyp, *nlyp;
 
 	/*
 	 * First, lock the client structure, so everyone else will
@@ -1904,6 +1905,17 @@ nfscl_recover(struct nfsclclient *clp, s
 	nmp = clp->nfsc_nmp;
 	if (nmp == NULL)
 		panic("nfscl recover");
+
+	/*
+	 * For now, just get rid of all layouts. There may be a need
+	 * to do LayoutCommit Ops with reclaim == true later.
+	 */
+	TAILQ_FOREACH_SAFE(lyp, &clp->nfsc_layout, nfsly_list, nlyp)
+		nfscl_freelayout(lyp);
+	TAILQ_INIT(&clp->nfsc_layout);
+	for (i = 0; i < NFSCLLAYOUTHASHSIZE; i++)
+		LIST_INIT(&clp->nfsc_layouthash[i]);
+
 	trycnt = 5;
 	do {
 		error = nfsrpc_setclient(nmp, clp, 1, cred, p);
@@ -2443,6 +2455,7 @@ nfscl_renewthread(struct nfsclclient *cl
 	struct nfscldevinfo *dip, *ndip;
 	struct nfscllayouthead rlh;
 	struct nfsclrecalllayout *recallp;
+	struct nfsclds *dsp;
 
 	cred = newnfs_getcred();
 	NFSLOCKCLSTATE();
@@ -2470,7 +2483,8 @@ nfscl_renewthread(struct nfsclclient *cl
 		    (clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID)) {
 			clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
 			clidrev = clp->nfsc_clientidrev;
-			error = nfsrpc_renew(clp, cred, p);
+			error = nfsrpc_renew(clp,
+			    TAILQ_FIRST(&clp->nfsc_nmp->nm_sess), cred, p);
 			if (error == NFSERR_CBPATHDOWN)
 			    cbpathdown = 1;
 			else if (error == NFSERR_STALECLIENTID ||
@@ -2482,6 +2496,25 @@ nfscl_renewthread(struct nfsclclient *cl
 			    (void) nfscl_hasexpired(clp, clidrev, p);
 		}
 
+		/* Do renews for any DS sessions. */
+checkdsrenew:
+		NFSLOCKMNT(clp->nfsc_nmp);
+		/* Skip first entry, since the MDS is handled above. */
+		dsp = TAILQ_FIRST(&clp->nfsc_nmp->nm_sess);
+		if (dsp != NULL)
+			dsp = TAILQ_NEXT(dsp, nfsclds_list);
+		while (dsp != NULL) {
+			if (dsp->nfsclds_expire <= NFSD_MONOSEC) {
+				dsp->nfsclds_expire = NFSD_MONOSEC +
+				    clp->nfsc_renew;
+				NFSUNLOCKMNT(clp->nfsc_nmp);
+				(void)nfsrpc_renew(clp, dsp, cred, p);
+				goto checkdsrenew;
+			}
+			dsp = TAILQ_NEXT(dsp, nfsclds_list);
+		}
+		NFSUNLOCKMNT(clp->nfsc_nmp);
+
 		TAILQ_INIT(&dh);
 		NFSLOCKCLSTATE();
 		if (cbpathdown)
@@ -2609,24 +2642,27 @@ printf("layrec io=%d\n", lyp->nfsly_refc
 				}
 
 				/* Handle any layout commits. */
-				LIST_FOREACH(flp, &lyp->nfsly_flayrw,
-				    nfsfl_list) {
-					if ((flp->nfsfl_flags & NFSFL_WRITTEN)
-					    != 0) {
-						lyp->nfsly_refcnt++;
-						flp->nfsfl_flags &=
-						    ~NFSFL_WRITTEN;
-						NFSUNLOCKCLSTATE();
+				if (!NFSHASNOLAYOUTCOMMIT(clp->nfsc_nmp)) {
+					LIST_FOREACH(flp, &lyp->nfsly_flayrw,
+					    nfsfl_list) {
+						if ((flp->nfsfl_flags &
+						    NFSFL_WRITTEN) != 0) {
+							lyp->nfsly_refcnt++;
+							flp->nfsfl_flags &=
+							    ~NFSFL_WRITTEN;
+							NFSUNLOCKCLSTATE();
 printf("do layoutcommit\n");
-						nfscl_dolayoutcommit(
-						    clp->nfsc_nmp, lyp, flp,
-						    cred, p);
-						NFSLOCKCLSTATE();
-						lyp->nfsly_refcnt--;
-						if (lyp->nfsly_refcnt == 0)
-							wakeup(
-							    &lyp->nfsly_refcnt);
-						goto tryagain2;
+							nfscl_dolayoutcommit(
+							    clp->nfsc_nmp, lyp,
+							    flp, cred, p);
+							NFSLOCKCLSTATE();
+							lyp->nfsly_refcnt--;
+							if (lyp->nfsly_refcnt ==
+							    0)
+							    wakeup(&lyp->
+								nfsly_refcnt);
+							goto tryagain2;
+						}
 					}
 				}
 
@@ -5061,8 +5097,8 @@ static void
 nfscl_dolayoutcommit(struct nfsmount *nmp, struct nfscllayout *lyp,
     struct nfsclflayout *flp, struct ucred *cred, NFSPROC_T *p)
 {
-	int error;
 	uint64_t len;
+	int error;
 
 	if (flp->nfsfl_end == UINT64_MAX)
 		len = UINT64_MAX;
@@ -5071,6 +5107,12 @@ nfscl_dolayoutcommit(struct nfsmount *nm
 	error = nfsrpc_layoutcommit(nmp, lyp->nfsly_fh, lyp->nfsly_fhlen,
 	    0, flp->nfsfl_off, len, lyp->nfsly_lastbyte, &lyp->nfsly_stateid,
 	    NFSLAYOUT_NFSV4_1_FILES, 0, NULL, cred, p, NULL);
+	if (error == NFSERR_NOTSUPP) {
+		/* If the server doesn't want it, don't bother doing it. */
+		NFSLOCKMNT(nmp);
+		nmp->nm_state |= NFSSTA_NOLAYOUTCOMMIT;
+		NFSUNLOCKMNT(nmp);
+	}
 }
 
 /*
@@ -5083,9 +5125,12 @@ nfscl_layoutcommit(vnode_t vp, NFSPROC_T
 	struct nfscllayout *lyp;
 	struct nfsclflayout *flp;
 	struct nfsnode *np = VTONFS(vp);
+	struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 
+	if (NFSHASNOLAYOUTCOMMIT(nmp))
+		return (0);
 	NFSLOCKCLSTATE();
-	clp = VFSTONFS(vnode_mount(vp))->nm_clp;
+	clp = nmp->nm_clp;
 	if (clp == NULL) {
 		NFSUNLOCKCLSTATE();
 		return (EPERM);


More information about the svn-src-projects mailing list