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

Rick Macklem rmacklem at FreeBSD.org
Thu Feb 23 03:16:10 UTC 2012


Author: rmacklem
Date: Thu Feb 23 03:16:09 2012
New Revision: 232017
URL: http://svn.freebsd.org/changeset/base/232017

Log:
  Implement the nfscl_getsameserver() function that searches the
  list of nfsclds structures for ones that are for the same server
  as the new one. If it finds a match that supports Data Server (DS),
  just return that one to use. If it finds a match that doesn't
  support DS, then return that one, so that the nfsess_sequenceid
  field can be use to sequence a new session. The list of nfsclds
  needed to be changed to a tailq so that the list could be maintained
  in temporal order (although the first one should be the only one
  that is for a MDS and, therefore, might not support DS). Flags
  were added to struct nfsclds to indicate MDS and/or DS support.

Modified:
  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/nfsclient/nfs_clrpcops.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_var.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Thu Feb 23 01:22:40 2012	(r232016)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Thu Feb 23 03:16:09 2012	(r232017)
@@ -440,7 +440,7 @@ int nfsrpc_exchangeid(struct nfsmount *,
     struct nfssockreq *, uint32_t, struct nfsclds **, struct ucred *,
     NFSPROC_T *);
 int nfsrpc_createsession(struct nfsmount *, struct nfsclsession *,
-    struct ucred *, NFSPROC_T *);
+    uint32_t, struct ucred *, NFSPROC_T *);
 int nfsrpc_destroysession(struct nfsmount *, struct nfsclclient *,
     struct ucred *, NFSPROC_T *);
 int nfsrpc_destroyclient(struct nfsmount *, struct nfsclclient *,

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Thu Feb 23 01:22:40 2012	(r232016)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Thu Feb 23 03:16:09 2012	(r232017)
@@ -70,20 +70,28 @@ struct nfsclsession {
 };
 
 /*
- * This structure holds the information used to access a Data Server (DS).
+ * This structure holds the session, clientid and related information
+ * needed for an NFSv4.1 Meta Data Server (MDS) or Data Server (DS).
  * It is malloc'd to the correct length.
  */
 struct nfsclds {
-	LIST_ENTRY(nfsclds)	nfsclds_list;
+	TAILQ_ENTRY(nfsclds)	nfsclds_list;
 	struct nfsclsession	nfsclds_sess;
 	struct mtx		nfsclds_mtx;
 	struct nfssockreq	*nfsclds_sockp;
-	uint16_t		nfsclds_haswriteverf;
+	uint16_t		nfsclds_flags;
 	uint16_t		nfsclds_servownlen;
 	uint8_t			nfsclds_verf[NFSX_VERF];
 	uint8_t			nfsclds_serverown[0];
 };
 
+/*
+ * Flags for nfsclds_flags.
+ */
+#define	NFSCLDS_HASWRITEVERF	0x0001
+#define	NFSCLDS_MDS		0x0002
+#define	NFSCLDS_DS		0x0004
+
 struct nfsclclient {
 	LIST_ENTRY(nfsclclient) nfsc_list;
 	struct nfsclownerhead	nfsc_owner;

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Thu Feb 23 01:22:40 2012	(r232016)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Thu Feb 23 03:16:09 2012	(r232017)
@@ -66,6 +66,19 @@ int nfstest_openallsetattr = 0;
 
 #define	DIRHDSIZ	(sizeof (struct dirent) - (MAXNAMLEN + 1))
 
+/*
+ * nfscl_getsameserver() can return one of three values:
+ * NFSDSP_USETHISSESSION - Use this session for the DS.
+ * NFSDSP_SEQTHISSESSION - Use the nfsclds_sequence field of this dsp for new
+ *     session.
+ * NFSDSP_NOTFOUND - No matching server was found.
+ */
+enum nfsclds_state {
+	NFSDSP_USETHISSESSION = 0,
+	NFSDSP_SEQTHISSESSION = 1,
+	NFSDSP_NOTFOUND = 2,
+};
+
 static int nfsrpc_setattrrpc(vnode_t , struct vattr *, nfsv4stateid_t *,
     struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, void *);
 static int nfsrpc_readrpc(vnode_t , struct uio *, struct ucred *,
@@ -101,7 +114,8 @@ 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 *);
+static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
+    struct nfsclds *, struct nfsclds **);
 
 /*
  * nfs null call from vfs.
@@ -818,12 +832,12 @@ nfsrpc_setclient(struct nfsmount *nmp, s
 if (error) printf("exch=%d\n",error);
 		if (error == 0) {
 			error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
-			    cred, p);
+			    dsp->nfsclds_sess.nfsess_sequenceid, cred, p);
 			if (error == 0) {
-				KASSERT(LIST_FIRST(&nmp->nm_sess) == NULL,
+				KASSERT(TAILQ_FIRST(&nmp->nm_sess) == NULL,
 				    ("nfscl session non-NULL"));
 				NFSLOCKMNT(nmp);
-				LIST_INSERT_HEAD(&nmp->nm_sess, dsp,
+				TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp,
 				    nfsclds_list);
 				NFSUNLOCKMNT(nmp);
 			} else
@@ -4389,7 +4403,10 @@ printf("v41fl=0x%x\n", v41flags);
 			NFSLOCKMNT(nmp);
 			nmp->nm_state |= NFSSTA_PNFS;
 			NFSUNLOCKMNT(nmp);
+			dsp->nfsclds_flags |= NFSCLDS_MDS;
 		}
+		if ((v41flags & NFSV4EXCH_USEPNFSDS) != 0)
+			dsp->nfsclds_flags |= NFSCLDS_DS;
 		nd->nd_repstat = nfsrv_mtostr(nd, dsp->nfsclds_serverown, len);
 		if (nd->nd_repstat == 0) {
 			mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
@@ -4411,7 +4428,7 @@ nfsmout:
  */
 int
 nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,
-    struct ucred *cred, NFSPROC_T *p)
+    uint32_t sequenceid, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd;
@@ -4422,8 +4439,8 @@ 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];
-	*tl++ = txdr_unsigned(sep->nfsess_sequenceid);
-printf("clseq0=0x%x\n",sep->nfsess_sequenceid);
+	*tl++ = txdr_unsigned(sequenceid);
+printf("clseq0=0x%x\n",sequenceid);
 	if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0)
 		*tl = txdr_unsigned(NFSV4CRSESS_PERSIST |
 		    NFSV4CRSESS_CONNBACKCHAN);
@@ -5055,6 +5072,8 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	struct nfssockreq *nrp;
 	struct nfsclds *dsp, *tdsp;
 	int error;
+	enum nfsclds_state retv;
+	uint32_t sequenceid;
 
 	KASSERT(nmp->nm_sockreq.nr_cred != NULL,
 	    ("nfsrpc_fillsa: NULL nr_cred"));
@@ -5106,8 +5125,10 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 		    &dsp, nrp->nr_cred, p);
 	if (error == 0) {
 		dsp->nfsclds_sockp = nrp;
-		tdsp = nfscl_getsameserver(nmp, dsp);
-		if (tdsp != NULL) {
+		NFSLOCKMNT(nmp);
+		retv = nfscl_getsameserver(nmp, dsp, &tdsp);
+		if (retv == NFSDSP_USETHISSESSION) {
+			NFSUNLOCKMNT(nmp);
 			/*
 			 * If there is already a session for this server,
 			 * use it.
@@ -5117,8 +5138,14 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 			*dspp = tdsp;
 			return (0);
 		}
+		if (retv == NFSDSP_SEQTHISSESSION) {
+			tdsp->nfsclds_sess.nfsess_sequenceid++;
+			sequenceid = tdsp->nfsclds_sess.nfsess_sequenceid;
+		} else
+			sequenceid = dsp->nfsclds_sess.nfsess_sequenceid;
+		NFSUNLOCKMNT(nmp);
 		error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
-		    nrp->nr_cred, p);
+		    sequenceid, nrp->nr_cred, p);
 	} else {
 		NFSFREECRED(nrp->nr_cred);
 		NFSFREEMUTEX(&nrp->nr_mtx);
@@ -5127,14 +5154,13 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	}
 	if (error == 0) {
 		/*
-		 * The first element should be the one for the MDS.
+		 * Put it at the end of the list. That way the list
+		 * is ordered by when the entry was added. This matters
+		 * since the one done first is the one that should be
+		 * used for sequencid'ing any subsequent create sessions.
 		 */
 		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);
+		TAILQ_INSERT_TAIL(&nmp->nm_sess, dsp, nfsclds_list);
 		NFSUNLOCKMNT(nmp);
 		*dspp = dsp;
 	} else if (dsp != NULL)
@@ -5498,9 +5524,9 @@ nfsrpc_writeds(vnode_t vp, struct uio *u
 			NFSUNLOCKMNT(nmp);
 		} else {
 			NFSLOCKDS(dsp);
-			if (dsp->nfsclds_haswriteverf == 0) {
+			if ((dsp->nfsclds_flags & NFSCLDS_HASWRITEVERF) == 0) {
 				NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
-				dsp->nfsclds_haswriteverf = 1;
+				dsp->nfsclds_flags |= NFSCLDS_HASWRITEVERF;
 			} else if (NFSBCMP(tl, dsp->nfsclds_verf, NFSX_VERF)) {
 				*must_commit = 1;
 				NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
@@ -5543,14 +5569,40 @@ nfscl_freenfsclds(struct nfsclds *dsp)
 	free(dsp, M_NFSCLDS);
 }
 
-static struct nfsclds *
-nfscl_getsameserver(struct nfsmount *nmp, struct nfsclds *newdsp)
+static enum nfsclds_state
+nfscl_getsameserver(struct nfsmount *nmp, struct nfsclds *newdsp,
+    struct nfsclds **retdspp)
 {
+	struct nfsclds *dsp, *cur_dsp;
 
 	/*
 	 * Search the list of nfsclds structures for one with the same
 	 * server.
 	 */
-	return (LIST_FIRST(&nmp->nm_sess));
+	cur_dsp = NULL;
+	TAILQ_FOREACH(dsp, &nmp->nm_sess, nfsclds_list) {
+		if (dsp->nfsclds_servownlen == newdsp->nfsclds_servownlen &&
+		    !NFSBCMP(dsp->nfsclds_serverown, newdsp->nfsclds_serverown,
+		     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) {
+				*retdspp = dsp;
+				return (NFSDSP_USETHISSESSION);
+			}
+
+			/*
+			 * Note the first match, so it can be used for
+			 * sequence'ing new sessions.
+			 */
+			if (cur_dsp == NULL)
+				cur_dsp = dsp;
+		}
+	}
+	if (cur_dsp != NULL) {
+		*retdspp = cur_dsp;
+		return (NFSDSP_SEQTHISSESSION);
+	}
+	return (NFSDSP_NOTFOUND);
 }
 

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clvfsops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clvfsops.c	Thu Feb 23 01:22:40 2012	(r232016)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clvfsops.c	Thu Feb 23 03:16:09 2012	(r232017)
@@ -1452,7 +1452,7 @@ bad:
 		NFSUNLOCKCLSTATE();
 		free(nmp->nm_clp, M_NFSCLCLIENT);
 	}
-	LIST_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
+	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
 		nfscl_freenfsclds(dsp);
 	FREE(nmp, M_NEWNFSMNT);
 	FREE(nam, M_SONAME);
@@ -1509,7 +1509,7 @@ nfs_unmount(struct mount *mp, int mntfla
 
 	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
 	mtx_destroy(&nmp->nm_mtx);
-	LIST_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
+	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
 		nfscl_freenfsclds(dsp);
 	FREE(nmp, M_NEWNFSMNT);
 out:

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfsmount.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfsmount.h	Thu Feb 23 01:22:40 2012	(r232016)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfsmount.h	Thu Feb 23 03:16:09 2012	(r232017)
@@ -70,7 +70,7 @@ struct	nfsmount {
 	int	nm_negnametimeo;	/* timeout for -ve entries (sec) */
 
 	/* Newnfs additions */
-	LIST_HEAD(, nfsclds) nm_sess;	/* Session(s) for NFSv4.1. */
+	TAILQ_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 */
@@ -113,7 +113,7 @@ struct	nfsmount {
  * 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))
+#define	NFSMNT_MDSSESSION(m)	(&(TAILQ_FIRST(&((m)->nm_sess))->nfsclds_sess))
 
 #ifndef NFS_DEFAULT_NAMETIMEO
 #define NFS_DEFAULT_NAMETIMEO		60


More information about the svn-src-projects mailing list