svn commit: r266958 - in projects/nfsv4.1-server/sys/fs: nfs nfsserver

Rick Macklem rmacklem at FreeBSD.org
Mon Jun 2 00:14:03 UTC 2014


Author: rmacklem
Date: Mon Jun  2 00:14:02 2014
New Revision: 266958
URL: http://svnweb.freebsd.org/changeset/base/266958

Log:
  Add support for the Want Delegation flags on Open to the NFSv4.1
  server. Also fix it so that it correctly reports that there is
  no backchannel in the Sequence reply.

Modified:
  projects/nfsv4.1-server/sys/fs/nfs/nfs.h
  projects/nfsv4.1-server/sys/fs/nfs/nfsproto.h
  projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c
  projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c

Modified: projects/nfsv4.1-server/sys/fs/nfs/nfs.h
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfs.h	Sun Jun  1 21:33:02 2014	(r266957)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfs.h	Mon Jun  2 00:14:02 2014	(r266958)
@@ -324,6 +324,11 @@ struct nfsreferral {
 #define	NFSLCK_SETATTR		0x02000000
 #define	NFSLCK_DELEGPURGE	0x04000000
 #define	NFSLCK_DELEGRETURN	0x08000000
+#define	NFSLCK_WANTWDELEG	0x10000000
+#define	NFSLCK_WANTRDELEG	0x20000000
+#define	NFSLCK_WANTNODELEG	0x40000000
+#define	NFSLCK_WANTBITS							\
+    (NFSLCK_WANTWDELEG | NFSLCK_WANTRDELEG | NFSLCK_WANTNODELEG)
 
 /* And bits for nid_flag */
 #define	NFSID_INITIALIZE	0x0001

Modified: projects/nfsv4.1-server/sys/fs/nfs/nfsproto.h
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfsproto.h	Sun Jun  1 21:33:02 2014	(r266957)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfsproto.h	Mon Jun  2 00:14:02 2014	(r266958)
@@ -512,15 +512,21 @@
 
 /*
  * Open result flags
- * (The first two are in the spec. The rest are used internally.)
+ * (The first four are in the spec. The rest are used internally.)
  */
 #define	NFSV4OPEN_RESULTCONFIRM		0x00000002
 #define	NFSV4OPEN_LOCKTYPEPOSIX		0x00000004
+#define	NFSV4OPEN_PRESERVEUNLINKED	0x00000008
+#define	NFSV4OPEN_MAYNOTIFYLOCK		0x00000020
 #define	NFSV4OPEN_RFLAGS 						\
-		(NFSV4OPEN_RESULTCONFIRM | NFSV4OPEN_LOCKTYPEPOSIX)
+    (NFSV4OPEN_RESULTCONFIRM | NFSV4OPEN_LOCKTYPEPOSIX |		\
+    NFSV4OPEN_PRESERVEUNLINKED | NFSV4OPEN_MAYNOTIFYLOCK)
 #define	NFSV4OPEN_RECALL		0x00010000
 #define	NFSV4OPEN_READDELEGATE		0x00020000
 #define	NFSV4OPEN_WRITEDELEGATE		0x00040000
+#define	NFSV4OPEN_WDRESOURCE		0x00080000
+#define	NFSV4OPEN_WDCONTENTION		0x00100000
+#define	NFSV4OPEN_WDNOTWANTED		0x00200000
 
 /*
  * NFS V4 File Handle types

Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c	Sun Jun  1 21:33:02 2014	(r266957)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c	Mon Jun  2 00:14:02 2014	(r266958)
@@ -2599,15 +2599,38 @@ nfsrvd_open(struct nfsrv_descript *nd, _
 	stp->ls_uid = nd->nd_cred->cr_uid;
 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
 	i = fxdr_unsigned(int, *tl++);
-	retext = -1;
+	retext = 0;
 	if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
 	    NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) {
-		retext = NFSV4OPEN_RESOURCE;
-		if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
-		    NFSV4OPEN_WANTPUSHDELEG)) == NFSV4OPEN_WANTNODELEG)
-			retext = NFSV4OPEN_NOTWANTED;
-		i &= ~(NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
-		    NFSV4OPEN_WANTPUSHDELEG);
+		retext = 1;
+		/* For now, ignore these. */
+		i &= ~(NFSV4OPEN_WANTPUSHDELEG | NFSV4OPEN_WANTSIGNALDELEG);
+		switch (i & NFSV4OPEN_WANTDELEGMASK) {
+		case NFSV4OPEN_WANTANYDELEG:
+			stp->ls_flags |= (NFSLCK_WANTRDELEG |
+			    NFSLCK_WANTWDELEG);
+			i &= ~NFSV4OPEN_WANTDELEGMASK;
+			break;
+		case NFSV4OPEN_WANTREADDELEG:
+			stp->ls_flags |= NFSLCK_WANTRDELEG;
+			i &= ~NFSV4OPEN_WANTDELEGMASK;
+			break;
+		case NFSV4OPEN_WANTWRITEDELEG:
+			stp->ls_flags |= NFSLCK_WANTWDELEG;
+			i &= ~NFSV4OPEN_WANTDELEGMASK;
+			break;
+		case NFSV4OPEN_WANTNODELEG:
+			stp->ls_flags |= NFSLCK_WANTNODELEG;
+			i &= ~NFSV4OPEN_WANTDELEGMASK;
+			break;
+		case NFSV4OPEN_WANTCANCEL:
+			printf("NFSv4: ignore Open WantCancel\n");
+			i &= ~NFSV4OPEN_WANTDELEGMASK;
+			break;
+		default:
+			/* nd_repstat will be set to NFSERR_INVAL below. */
+			break;
+		};
 	}
 	switch (i) {
 	case NFSV4OPEN_ACCESSREAD:
@@ -2910,16 +2933,19 @@ nfsrvd_open(struct nfsrv_descript *nd, _
 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD);
 		else if (rflags & NFSV4OPEN_WRITEDELEGATE)
 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE);
-		else if (retext != -1) {
+		else if (retext != 0) {
 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT);
-			if (retext == NFSV4OPEN_RESOURCE ||
-			    retext == NFSV4OPEN_CONTENTION) {
+			if ((rflags & NFSV4OPEN_WDCONTENTION) != 0) {
+				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+				*tl++ = txdr_unsigned(NFSV4OPEN_CONTENTION);
+				*tl = newnfs_false;
+			} else if ((rflags & NFSV4OPEN_WDRESOURCE) != 0) {
 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
-				*tl++ = txdr_unsigned(retext);
+				*tl++ = txdr_unsigned(NFSV4OPEN_RESOURCE);
 				*tl = newnfs_false;
 			} else {
 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
-				*tl = txdr_unsigned(retext);
+				*tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
 			}
 		} else
 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE);

Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c	Sun Jun  1 21:33:02 2014	(r266957)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c	Mon Jun  2 00:14:02 2014	(r266958)
@@ -153,7 +153,6 @@ nfsrv_setclient(struct nfsrv_descript *n
 	/*
 	 * Check for state resource limit exceeded.
 	 */
-printf("in nfsrv_setcl\n");
 	if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) {
 		error = NFSERR_RESOURCE;
 		goto out;
@@ -211,7 +210,6 @@ printf("in nfsrv_setcl\n");
 			NFSUNLOCKV4ROOTMUTEX();
 			confirmp->lval[1] = 0;
 			error = NFSERR_NOENT;
-printf("reconfirming\n");
 			goto out;
 		}
 		/*
@@ -259,7 +257,6 @@ printf("reconfirming\n");
 		if (zapit)
 			nfsrv_zapclient(clp, p);
 		*new_clpp = NULL;
-printf("new cl\n");
 		goto out;
 	}
 
@@ -375,7 +372,6 @@ printf("new cl\n");
 		NFSUNLOCKSTATE();
 		nfsrv_zapclient(clp, p);
 		*new_clpp = NULL;
-printf("new cl2\n");
 		goto out;
 	}
 
@@ -420,7 +416,6 @@ printf("new cl2\n");
 		newnfsstats.srvclients++;
 		nfsrv_openpluslock++;
 		nfsrv_clients++;
-printf("new cl3\n");
 	}
 	NFSLOCKV4ROOTMUTEX();
 	nfsv4_unlock(&nfsv4rootfs_lock, 1);
@@ -578,18 +573,14 @@ nfsrv_getclient(nfsquad_t clientid, int 
 		    clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
 		    if (clp->lc_program)
 			clp->lc_flags |= LCL_NEEDSCBNULL;
-printf("prog=%d\n", clp->lc_program);
 		    /* For NFSv4.1, link the session onto the client. */
 		    if (nsep != NULL) {
-printf("nsep not null\n");
 			/* Hold a reference on the xprt for a backchannel. */
 			if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN)
 			    != 0 && clp->lc_req.nr_client == NULL) {
-printf("set backch\n");
 			    clp->lc_req.nr_client = (struct __rpc_client *)
 				clnt_bck_create(nd->nd_xprt->xp_socket,
 				cbprogram, NFSV4_CBVERS);
-printf("cbcl=%p\n", clp->lc_req.nr_client);
 			    if (clp->lc_req.nr_client != NULL) {
 				SVC_ACQUIRE(nd->nd_xprt);
 				nd->nd_xprt->xp_p2 =
@@ -2896,13 +2887,20 @@ tryagain:
 		    /*
 		     * This is where we can choose to issue a delegation.
 		     */
-		    if (delegate && nfsrv_issuedelegs &&
-			writedeleg && !NFSVNO_EXRDONLY(exp) &&
-			(nfsrv_writedelegifpos || !readonly) &&
-			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
-			 LCL_CALLBACKSON &&
-			!NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
-			NFSVNO_DELEGOK(vp)) {
+		    if (delegate == 0 || writedeleg == 0 ||
+			NFSVNO_EXRDONLY(exp) || (readonly != 0 &&
+			nfsrv_writedelegifpos == 0) ||
+			!NFSVNO_DELEGOK(vp) ||
+			(new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 ||
+			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
+			 LCL_CALLBACKSON)
+			*rflagsp |= NFSV4OPEN_WDCONTENTION;
+		    else if (nfsrv_issuedelegs == 0 ||
+			NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
+			*rflagsp |= NFSV4OPEN_WDRESOURCE;
+		    else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
+			*rflagsp |= NFSV4OPEN_WDNOTWANTED;
+		    else {
 			new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
 			new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
 			    = clp->lc_clientid.lval[0];
@@ -2951,12 +2949,17 @@ tryagain:
 		    /*
 		     * This is where we can choose to issue a delegation.
 		     */
-		    if (delegate && nfsrv_issuedelegs &&
-			(writedeleg || readonly) &&
-			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
-			 LCL_CALLBACKSON &&
-			!NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
-			NFSVNO_DELEGOK(vp)) {
+		    if (delegate == 0 || (writedeleg == 0 && readonly == 0) ||
+			!NFSVNO_DELEGOK(vp) ||
+			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
+			 LCL_CALLBACKSON)
+			*rflagsp |= NFSV4OPEN_WDCONTENTION;
+		    else if (nfsrv_issuedelegs == 0 ||
+			NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
+			*rflagsp |= NFSV4OPEN_WDRESOURCE;
+		    else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
+			*rflagsp |= NFSV4OPEN_WDNOTWANTED;
+		    else {
 			new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
 			new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
 			    = clp->lc_clientid.lval[0];
@@ -2965,7 +2968,8 @@ tryagain:
 			new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
 			    = nfsrv_nextstateindex(clp);
 			if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
-			    (nfsrv_writedelegifpos || !readonly)) {
+			    (nfsrv_writedelegifpos || !readonly) &&
+			    (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) {
 			    new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
 				NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
 			    *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
@@ -3012,6 +3016,61 @@ tryagain:
 		} else if ((nd->nd_flag & ND_NFSV41) != 0) {
 			/* NFSv4.1 never needs confirmation. */
 			new_stp->ls_flags = 0;
+
+			/*
+			 * This is where we can choose to issue a delegation.
+			 */
+			if (delegate && nfsrv_issuedelegs &&
+			    (writedeleg || readonly) &&
+			    (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
+			     LCL_CALLBACKSON &&
+			    !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
+			    NFSVNO_DELEGOK(vp) &&
+			    ((nd->nd_flag & ND_NFSV41) == 0 ||
+			     (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) {
+				new_deleg->ls_stateid.seqid =
+				    delegstateidp->seqid = 1;
+				new_deleg->ls_stateid.other[0] =
+				    delegstateidp->other[0]
+				    = clp->lc_clientid.lval[0];
+				new_deleg->ls_stateid.other[1] =
+				    delegstateidp->other[1]
+				    = clp->lc_clientid.lval[1];
+				new_deleg->ls_stateid.other[2] =
+				    delegstateidp->other[2]
+				    = nfsrv_nextstateindex(clp);
+				if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
+				    (nfsrv_writedelegifpos || !readonly) &&
+				    ((nd->nd_flag & ND_NFSV41) == 0 ||
+				     (new_stp->ls_flags & NFSLCK_WANTRDELEG) ==
+				     0)) {
+					new_deleg->ls_flags =
+					    (NFSLCK_DELEGWRITE |
+					     NFSLCK_READACCESS |
+					     NFSLCK_WRITEACCESS);
+					*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
+				} else {
+					new_deleg->ls_flags =
+					    (NFSLCK_DELEGREAD |
+					     NFSLCK_READACCESS);
+					*rflagsp |= NFSV4OPEN_READDELEGATE;
+				}
+				new_deleg->ls_uid = new_stp->ls_uid;
+				new_deleg->ls_lfp = lfp;
+				new_deleg->ls_clp = clp;
+				new_deleg->ls_filerev = filerev;
+				new_deleg->ls_compref = nd->nd_compref;
+				LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg,
+				    ls_file);
+				LIST_INSERT_HEAD(NFSSTATEHASH(clp,
+				    new_deleg->ls_stateid), new_deleg, ls_hash);
+				LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg,
+				    ls_list);
+				new_deleg = NULL;
+				newnfsstats.srvdelegates++;
+				nfsrv_openpluslock++;
+				nfsrv_delegatecnt++;
+			}
 		} else {
 			*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
 			new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
@@ -5576,7 +5635,6 @@ nfsrv_checksequence(struct nfsrv_descrip
 {
 	struct nfsdsession *sep;
 	struct nfssessionhash *shp;
-	CLIENT *cl;
 	int error;
 	SVCXPRT *savxprt;
 
@@ -5614,11 +5672,10 @@ nfsrv_checksequence(struct nfsrv_descrip
 		SVC_RELEASE(savxprt);
 	}
 
-	cl = sep->sess_clp->lc_req.nr_client;
-	if (cl == NULL)
+	*sflagsp = 0;
+	if (sep->sess_clp->lc_req.nr_client == NULL)
 		*sflagsp |= NFSV4SEQ_CBPATHDOWN;
 	NFSUNLOCKSESSION(shp);
-	*sflagsp = 0;
 	if (error == NFSERR_EXPIRED) {
 		*sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED;
 		error = 0;


More information about the svn-src-projects mailing list