Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Jan 2012 03:38:09 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r230041 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient
Message-ID:  <201201130338.q0D3c9dE039573@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Fri Jan 13 03:38:08 2012
New Revision: 230041
URL: http://svn.freebsd.org/changeset/base/230041

Log:
  Update the layout handling functions and add new functions that hang
  the layouts and device info structures for pNFS off of the client id
  structure. Also, cleaned up the indentation of the client id structure.
  This code is still untested at this point.

Modified:
  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_clrpcops.c
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c	Fri Jan 13 02:33:55 2012	(r230040)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c	Fri Jan 13 03:38:08 2012	(r230041)
@@ -104,6 +104,7 @@ MALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL dir
     "New NFS directory offset data");
 MALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback",
     "New NFS local lock rollback");
+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");
 

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Fri Jan 13 02:33:55 2012	(r230040)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Fri Jan 13 03:38:08 2012	(r230041)
@@ -74,7 +74,7 @@ struct nfscllockowner;
 struct nfscllock;
 struct nfscldeleg;
 struct nfscllayout;
-struct nfsclfldevinfo;
+struct nfscldevinfo;
 struct nfsv4lock;
 struct nfsvattr;
 struct nfs_vattr;
@@ -444,10 +444,11 @@ int nfsrpc_destroysession(struct nfsmoun
     struct ucred *, NFSPROC_T *);
 int nfsrpc_destroyclient(struct nfsmount *, struct nfsclclient *,
     struct ucred *, NFSPROC_T *);
-int nfsrpc_layoutget(vnode_t, int, uint64_t, uint64_t, uint64_t,
-    struct nfscllayout *, struct ucred *, NFSPROC_T *, void *);
+int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t, uint64_t,
+    uint64_t, nfsv4stateid_t *, int *, struct nfsclflayouthead *,
+    struct ucred *, NFSPROC_T *, void *);
 int nfsrpc_getdeviceinfo(struct nfsmount *, uint8_t *, int, uint32_t *,
-    struct nfsclfldevinfo **, struct ucred *, NFSPROC_T *);
+    struct nfscldevinfo **, struct ucred *, NFSPROC_T *);
 int nfsrpc_layoutcommit(vnode_t, off_t, uint64_t, int, nfsv4stateid_t *, int,
     off_t, int, struct timespec, int, int, uint8_t *, int *, uint64_t *,
     struct ucred *, NFSPROC_T *, void *);
@@ -514,6 +515,13 @@ void nfscl_deleggetmodtime(vnode_t, stru
 int nfscl_tryclose(struct nfsclopen *, struct ucred *,
     struct nfsmount *, NFSPROC_T *);
 void nfscl_cleanup(NFSPROC_T *);
+int nfscl_layout(struct nfsmount *, u_int8_t *, int, nfsv4stateid_t *, int,
+    struct nfsclflayouthead *, struct nfscllayout **, struct ucred *,
+    NFSPROC_T *);
+struct nfscllayout *nfscl_getlayout(struct nfsmount *, uint8_t *, int);
+void nfscl_rellayout(struct nfscllayout *);
+void nfscl_reldevinfo(struct nfscldevinfo *);
+void nfscl_adddevinfo(struct nfsmount *, struct nfscldevinfo *);
 
 /* nfs_clport.c */
 int nfscl_nget(mount_t, vnode_t, struct nfsfh *,

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Fri Jan 13 02:33:55 2012	(r230040)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Fri Jan 13 03:38:08 2012	(r230041)
@@ -43,9 +43,18 @@ LIST_HEAD(nfscldeleghash, nfscldeleg);
 TAILQ_HEAD(nfscllayouthead, nfscllayout);
 LIST_HEAD(nfscllayouthash, nfscllayout);
 LIST_HEAD(nfsclflayouthead, nfsclflayout);
+TAILQ_HEAD(nfscldevinfohead, nfscldevinfo);
+LIST_HEAD(nfscldevinfohash, nfscldevinfo);
 #define	NFSCLDELEGHASHSIZE	256
-#define	NFSCLDELEGHASH(c, f, l)						\
+#define	NFSCLDELEGHASH(c, f, l)							\
 	(&((c)->nfsc_deleghash[ncl_hash((f), (l)) % NFSCLDELEGHASHSIZE]))
+#define	NFSCLLAYOUTHASHSIZE	256
+#define	NFSCLLAYOUTHASH(c, f, l)						\
+	(&((c)->nfsc_layouthash[ncl_hash((f), (l)) % NFSCLLAYOUTHASHSIZE]))
+#define	NFSCLDEVINFOHASHSIZE	16
+#define	NFSCLDEVINFOHASH(c, f)							\
+	(&((c)->nfsc_devinfohash[ncl_hash((f), NFSX_V4DEVICEID) %		\
+	     NFSCLDEVINFOHASHSIZE]))
 
 /* Structure for NFSv4.1 session stuff. */
 struct nfsclsession {
@@ -64,18 +73,22 @@ struct nfsclclient {
 	struct nfsclownerhead	nfsc_owner;
 	struct nfscldeleghead	nfsc_deleg;
 	struct nfscldeleghash	nfsc_deleghash[NFSCLDELEGHASHSIZE];
-	struct nfsv4lock nfsc_lock;
+	struct nfscllayouthead	nfsc_layout;
+	struct nfscllayouthash	nfsc_layouthash[NFSCLLAYOUTHASHSIZE];
+	struct nfscldevinfohead	nfsc_devinfo;
+	struct nfscldevinfohash	nfsc_devinfohash[NFSCLDEVINFOHASHSIZE];
+	struct nfsv4lock	nfsc_lock;
 	struct nfsclsession	nfsc_sess;
-	struct proc	*nfsc_renewthread;
-	struct nfsmount	*nfsc_nmp;
-	time_t		nfsc_expire;
-	u_int32_t	nfsc_clientidrev;
-	u_int32_t	nfsc_renew;
-	u_int32_t	nfsc_cbident;
-	u_int16_t	nfsc_flags;
-	u_int16_t	nfsc_backslots;	/* Number of back channel slots. */
-	u_int16_t	nfsc_idlen;
-	u_int8_t	nfsc_id[1];	/* Malloc'd to correct length */
+	struct proc		*nfsc_renewthread;
+	struct nfsmount		*nfsc_nmp;
+	time_t			nfsc_expire;
+	u_int32_t		nfsc_clientidrev;
+	u_int32_t		nfsc_renew;
+	u_int32_t		nfsc_cbident;
+	u_int16_t		nfsc_flags;
+	u_int16_t		nfsc_backslots;	/* # of back channel slots. */
+	u_int16_t		nfsc_idlen;
+	u_int8_t		nfsc_id[1];	/* Malloc'd to correct length */
 };
 
 #define	nfsc_mtx	nfsc_sess.nfsess_mtx
@@ -209,6 +222,7 @@ struct nfscllayout {
 	nfsv4stateid_t			nfsly_stateid;
 	struct nfsclflayouthead		nfsly_flay;
 	struct nfsclclient		*nfsly_clp;
+	uint32_t			nfsly_refcnt;
 	uint16_t			nfsly_retonclose;
 	uint16_t			nfsly_fhlen;
 	uint8_t				nfsly_fh[1];
@@ -240,11 +254,12 @@ struct nfsclflayout {
  *   of them. (This implies a limit of 256 on nfsdi_addrcnt, since the
  *   indices select which address.)
  */
-struct nfsclfldevinfo {
-	TAILQ_ENTRY(nfsclfldevinfo)	nfsdi_list;
-	LIST_ENTRY(nfsclfldevinfo)	nfsdi_hash;
+struct nfscldevinfo {
+	TAILQ_ENTRY(nfscldevinfo)	nfsdi_list;
+	LIST_ENTRY(nfscldevinfo)	nfsdi_hash;
 	uint8_t				nfsdi_deviceid[NFSX_V4DEVICEID];
 	struct nfsclclient		*nfsdi_clp;
+	uint32_t			nfsdi_refcnt;
 	uint16_t			nfsdi_stripecnt;
 	uint16_t			nfsdi_addrcnt;
 	struct sockaddr_storage		nfsdi_data[1];
@@ -255,7 +270,7 @@ struct nfsclfldevinfo {
  * Return a pointer to the address at "pos".
  */
 static __inline struct sockaddr_storage *
-nfsfldi_addr(struct nfsclfldevinfo *ndi, int pos)
+nfsfldi_addr(struct nfscldevinfo *ndi, int pos)
 {
 
 	if (pos >= ndi->nfsdi_addrcnt)
@@ -267,7 +282,7 @@ nfsfldi_addr(struct nfsclfldevinfo *ndi,
  * Return the Nth ("pos") stripe index.
  */
 static __inline int
-nfsfldi_stripeindex(struct nfsclfldevinfo *ndi, int pos)
+nfsfldi_stripeindex(struct nfscldevinfo *ndi, int pos)
 {
 	uint8_t *valp;
 
@@ -282,7 +297,7 @@ nfsfldi_stripeindex(struct nfsclfldevinf
  * Set the Nth ("pos") stripe index to "val".
  */
 static __inline void
-nfsfldi_setstripeindex(struct nfsclfldevinfo *ndi, int pos, uint8_t val)
+nfsfldi_setstripeindex(struct nfscldevinfo *ndi, int pos, uint8_t val)
 {
 	uint8_t *valp;
 

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsport.h	Fri Jan 13 02:33:55 2012	(r230040)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsport.h	Fri Jan 13 03:38:08 2012	(r230041)
@@ -428,13 +428,13 @@ struct ext_nfsstats {
 #include <fs/nfs/rpcv2.h>
 #include <fs/nfs/nfsproto.h>
 #include <fs/nfs/nfs.h>
+#include <fs/nfs/nfsclstate.h>
 #include <fs/nfs/nfs_var.h>
 #include <fs/nfs/nfsm_subs.h>
 #include <fs/nfs/nfsrvcache.h>
 #include <fs/nfs/nfsrvstate.h>
 #include <fs/nfs/xdr_subs.h>
 #include <fs/nfs/nfscl.h>
-#include <fs/nfs/nfsclstate.h>
 #include <nfsclient/nfsargs.h>
 #include <fs/nfsclient/nfsmount.h>
 
@@ -732,6 +732,7 @@ MALLOC_DECLARE(M_NEWNFSV4NODE);
 MALLOC_DECLARE(M_NEWNFSDIRECTIO);
 MALLOC_DECLARE(M_NEWNFSMNT);
 MALLOC_DECLARE(M_NEWNFSDROLLBACK);
+MALLOC_DECLARE(M_NEWNFSLAYOUT);
 MALLOC_DECLARE(M_NEWNFSFLAYOUT);
 MALLOC_DECLARE(M_NEWNFSDEVINFO);
 #define	M_NFSRVCACHE	M_NEWNFSRVCACHE
@@ -753,6 +754,7 @@ MALLOC_DECLARE(M_NEWNFSDEVINFO);
 #define	M_NFSV4NODE	M_NEWNFSV4NODE
 #define	M_NFSDIRECTIO	M_NEWNFSDIRECTIO
 #define	M_NFSDROLLBACK	M_NEWNFSDROLLBACK
+#define	M_NFSLAYOUT	M_NEWNFSLAYOUT
 #define	M_NFSFLAYOUT	M_NEWNFSFLAYOUT
 #define	M_NFSDEVINFO	M_NEWNFSDEVINFO
 

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jan 13 02:33:55 2012	(r230040)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jan 13 03:38:08 2012	(r230041)
@@ -85,6 +85,8 @@ static int nfsrpc_locku(struct nfsrv_des
     u_int32_t, struct ucred *, NFSPROC_T *, int);
 static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *,
     struct acl *, nfsv4stateid_t *, void *);
+static int nfsrpc_getlayout(struct nfsmount *, struct nfsfh *, int, uint32_t *,
+    nfsv4stateid_t *, struct ucred *, NFSPROC_T *);
 
 /*
  * nfs null call from vfs.
@@ -222,6 +224,8 @@ nfsrpc_open(vnode_t vp, int amode, struc
 	struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 	u_int32_t mode, clidrev;
 	int ret, newone, error, expireret = 0, retrycnt;
+	int iomode;
+	nfsv4stateid_t stateid;
 
 	/*
 	 * For NFSv4, Open Ops are only done on Regular Files.
@@ -229,10 +233,13 @@ nfsrpc_open(vnode_t vp, int amode, struc
 	if (vnode_vtype(vp) != VREG)
 		return (0);
 	mode = 0;
+	iomode = NFSLAYOUTIOMODE_READ;
 	if (amode & FREAD)
 		mode |= NFSV4OPEN_ACCESSREAD;
-	if (amode & FWRITE)
+	if (amode & FWRITE) {
 		mode |= NFSV4OPEN_ACCESSWRITE;
+		iomode = NFSLAYOUTIOMODE_RW;
+	}
 	nfhp = np->n_fhp;
 
 	retrycnt = 0;
@@ -284,6 +291,16 @@ else printf(" fhl=0\n");
 				    op->nfso_own->nfsow_clp,
 				    nfhp->nfh_fh, nfhp->nfh_len, cred, p, &dp);
 			}
+
+			/* Try and get a Layout, if it is supported. */
+			if (error == 0 && NFSHASPNFS(nmp)) {
+				stateid.seqid = op->nfso_stateid.seqid;
+				stateid.other[0] = op->nfso_stateid.other[0];
+				stateid.other[1] = op->nfso_stateid.other[1];
+				stateid.other[2] = op->nfso_stateid.other[2];
+				(void)nfsrpc_getlayout(nmp, nfhp, iomode,
+				    NULL, &stateid, cred, p);
+			}
 		} else {
 			error = EIO;
 		}
@@ -4301,6 +4318,11 @@ printf("exch err=%d reps=%d\n",error,nd-
 		clp->nfsc_sequenceid = fxdr_unsigned(uint32_t, *tl++);
 		v41flags = fxdr_unsigned(uint32_t, *tl);
 printf("v41fl=0x%x\n", v41flags);
+		if ((v41flags & NFSV4EXCH_USEPNFSMDS) != 0) {
+			NFSLOCKMNT(nmp);
+			nmp->nm_state |= NFSSTA_PNFS;
+			NFSUNLOCKMNT(nmp);
+		}
 	}
 	error = nd->nd_repstat;
 nfsmout:
@@ -4457,21 +4479,20 @@ nfsrpc_destroyclient(struct nfsmount *nm
  * Do the NFSv4.1 LayoutGet.
  */
 int
-nfsrpc_layoutget(vnode_t vp, int iomode, uint64_t offset, uint64_t len,
-    uint64_t minlen, struct nfscllayout *lp, struct ucred *cred,
+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)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
-	struct nfsfh *fhp;
-	struct nfsclflayout *flp, *nflp, *tflp;
-	struct nfsnode *np;
-	int cnt, error, fhcnt, fhlen, i, j;
+	struct nfsfh *nfhp;
+	struct nfsclflayout *flp, *prevflp, *tflp;
+	int cnt, error, fhcnt, nfhlen, i, j;
 	uint8_t *cp;
 
-	np = VTONFS(vp);
 	flp = NULL;
-	NFSCL_REQSTART(nd, NFSPROC_LAYOUTGET, vp);
+	nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL);
 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
 	    NFSX_STATEID);
 	*tl++ = newnfs_false;		/* Don't signal availability. */
@@ -4483,25 +4504,27 @@ nfsrpc_layoutget(vnode_t vp, int iomode,
 	tl += 2;
 	txdr_hyper(minlen, tl);
 	tl += 2;
-	*tl++ = lp->nfsly_stateid.seqid;
-	*tl++ = lp->nfsly_stateid.other[0];
-	*tl++ = lp->nfsly_stateid.other[1];
-	*tl++ = lp->nfsly_stateid.other[2];
+	*tl++ = stateidp->seqid;
+	*tl++ = stateidp->other[0];
+	*tl++ = stateidp->other[1];
+	*tl++ = stateidp->other[2];
 	*tl = txdr_unsigned(100000);	/* take a large layout list */
 	nd->nd_flag |= ND_USEGSSNAME;
-	error = nfscl_request(nd, vp, p, cred, stuff);
+	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
+	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_STATEID);
-		if (*tl++ != 0) {
-			lp->nfsly_retonclose = 1;
-printf("layg setting retonclose\n");
-		}
-		lp->nfsly_stateid.seqid = *tl++;
-		lp->nfsly_stateid.other[0] = *tl++;
-		lp->nfsly_stateid.other[1] = *tl++;
-		lp->nfsly_stateid.other[2] = *tl++;
+		if (*tl++ != 0)
+			*retonclosep = 1;
+		else
+			*retonclosep = 0;
+printf("retonclose=%d\n", *retonclosep);
+		stateidp->seqid = *tl++;
+		stateidp->other[0] = *tl++;
+		stateidp->other[1] = *tl++;
+		stateidp->other[2] = *tl++;
 		cnt = fxdr_unsigned(int, *tl);
 printf("layg cnt=%d\n", cnt);
 		if (cnt <= 0 || cnt > 10000) {
@@ -4551,35 +4574,31 @@ printf("layg iom=%d\n", iomode);
 			}
 			for (j = 0; j < fhcnt; j++) {
 				NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
-				fhlen = fxdr_unsigned(int, *tl);
-				if (fhlen <= 0 || fhlen > NFSX_V4FHMAX) {
+				nfhlen = fxdr_unsigned(int, *tl);
+				if (nfhlen <= 0 || nfhlen > NFSX_V4FHMAX) {
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
-				fhp = malloc(sizeof(*fhp) + fhlen - 1,
+				nfhp = malloc(sizeof(*nfhp) + nfhlen - 1,
 				    M_NFSFH, M_WAITOK);
-				flp->nfsfl_fh[j] = fhp;
+				flp->nfsfl_fh[j] = nfhp;
 				flp->nfsfl_fhcnt++;
-				fhp->nfh_len = fhlen;
+				nfhp->nfh_len = nfhlen;
 				NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(fhlen));
-				NFSBCOPY(cp, fhp->nfh_fh, fhlen);
+				NFSBCOPY(cp, nfhp->nfh_fh, nfhlen);
 			}
-			if (LIST_EMPTY(&lp->nfsly_flay) ||
-			    LIST_FIRST(&lp->nfsly_flay)->nfsfl_off >=
-			    flp->nfsfl_off)
-				LIST_INSERT_HEAD(&lp->nfsly_flay, flp,
-				    nfsfl_list);
-			else {
-				nflp = LIST_FIRST(&lp->nfsly_flay);
-				tflp = LIST_NEXT(nflp, nfsfl_list);
-				while (tflp != NULL) {
-					if (tflp->nfsfl_off >= flp->nfsfl_off)
-						break;
-					nflp = tflp;
-					tflp = LIST_NEXT(tflp, nfsfl_list);
-				}
-				LIST_INSERT_AFTER(nflp, flp, nfsfl_list);
+			/* Maintain the list in increasing offset order. */
+			tflp = LIST_FIRST(flhp);
+			prevflp = NULL;
+			while (tflp != NULL &&
+			    tflp->nfsfl_off < flp->nfsfl_off) {
+				prevflp = tflp;
+				tflp = LIST_NEXT(tflp, nfsfl_list);
 			}
+			if (prevflp == NULL)
+				LIST_INSERT_HEAD(flhp, flp, nfsfl_list);
+			else
+				LIST_INSERT_AFTER(prevflp, flp, nfsfl_list);
 			flp = NULL;
 		}
 	}
@@ -4600,14 +4619,14 @@ nfsmout:
  */
 int
 nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype,
-    uint32_t *notifybitsp, struct nfsclfldevinfo **ndip, struct ucred *cred,
+    uint32_t *notifybitsp, struct nfscldevinfo **ndip, struct ucred *cred,
     NFSPROC_T *p)
 {
 	uint32_t cnt, *tl;
 	struct nfsrv_descript nfsd;
 	struct sockaddr_storage ss, *sa;
 	struct nfsrv_descript *nd = &nfsd;
-	struct nfsclfldevinfo *ndi;
+	struct nfscldevinfo *ndi;
 	int addrcnt, bitcnt, error, i, isudp, j, pos, safilled, stripecnt;
 	uint8_t stripeindex;
 
@@ -4659,6 +4678,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		    sizeof(struct sockaddr_storage),
 		    M_NFSDEVINFO, M_WAITOK);
 		NFSBCOPY(deviceid, ndi->nfsdi_deviceid, NFSX_V4DEVICEID);
+		ndi->nfsdi_refcnt = 0;
 		ndi->nfsdi_stripecnt = stripecnt;
 		ndi->nfsdi_addrcnt = addrcnt;
 		/* Fill in the stripe indices. */
@@ -4877,3 +4897,43 @@ nfsmout:
 	return (error);
 }
 
+/*
+ * Called from nfsrpc_open() to acquire a layout and associated device
+ * info. A separate function mostly to avoid excessive indentation in
+ * nfsrpc_open().
+ */
+static int
+nfsrpc_getlayout(struct nfsmount *nmp, struct nfsfh *nfhp, int iomode,
+    uint32_t *notifybitsp, nfsv4stateid_t *stateidp, struct ucred *cred,
+    NFSPROC_T *p)
+{
+	struct nfscllayout *lyp;
+	struct nfsclflayout *flp;
+	struct nfscldevinfo *dip;
+	struct nfsclflayouthead flh;
+	int error = 0, retonclose;
+
+	lyp = nfscl_getlayout(nmp, nfhp->nfh_fh, nfhp->nfh_len);
+	if (lyp == NULL) {
+		LIST_INIT(&flh);
+		error = nfsrpc_layoutget(nmp, nfhp->nfh_fh, nfhp->nfh_len,
+		    iomode, (uint64_t)0, INT64_MAX, (uint64_t)(4 * NFS_MAXDATA),
+		    stateidp, &retonclose, &flh, cred, p, NULL);
+		if (error == 0)
+			LIST_FOREACH(flp, &flh, nfsfl_list) {
+				error = nfsrpc_getdeviceinfo(nmp,
+				    flp->nfsfl_dev, NFSLAYOUT_NFSV4_1_FILES,
+				    notifybitsp, &dip, cred, p);
+				if (error != 0)
+					break;
+				nfscl_adddevinfo(nmp, dip);
+			}
+		if (error == 0)
+			error = nfscl_layout(nmp, nfhp->nfh_fh, nfhp->nfh_len,
+			    stateidp, retonclose, &flh, &lyp, cred, p);
+	}
+	if (lyp != NULL)
+		nfscl_rellayout(lyp);
+	return (error);
+}
+

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Fri Jan 13 02:33:55 2012	(r230040)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Fri Jan 13 03:38:08 2012	(r230041)
@@ -92,9 +92,11 @@ NFSCLSTATEMUTEX;
 int nfscl_inited = 0;
 struct nfsclhead nfsclhead;	/* Head of clientid list */
 int nfscl_deleghighwater = NFSCLDELEGHIGHWATER;
+int nfscl_layouthighwater = NFSCLLAYOUTHIGHWATER;
 #endif	/* !APPLEKEXT */
 
 static int nfscl_delegcnt = 0;
+static int nfscl_layoutcnt = 0;
 static int nfscl_getopen(struct nfsclownerhead *, u_int8_t *, int, u_int8_t *,
     u_int8_t *, u_int32_t, struct nfscllockowner **, struct nfsclopen **);
 static void nfscl_clrelease(struct nfsclclient *);
@@ -115,6 +117,9 @@ static struct nfsclclient *nfscl_getclnt
 static struct nfsclclient *nfscl_getclntsess(uint8_t *);
 static struct nfscldeleg *nfscl_finddeleg(struct nfsclclient *, u_int8_t *,
     int);
+static struct nfscllayout *nfscl_findlayout(struct nfsclclient *, u_int8_t *,
+    int);
+static struct nfscldevinfo *nfscl_finddevinfo(struct nfsclclient *, uint8_t *);
 static int nfscl_checkconflict(struct nfscllockownerhead *, struct nfscllock *,
     u_int8_t *, struct nfscllock **);
 static void nfscl_freealllocks(struct nfscllockownerhead *, int);
@@ -148,6 +153,8 @@ static int nfscl_trydelegreturn(struct n
     struct nfsmount *, NFSPROC_T *);
 static void nfscl_emptylockowner(struct nfscllockowner *,
     struct nfscllockownerfhhead *);
+static void nfscl_mergeflayouts(struct nfsclflayouthead *,
+    struct nfsclflayouthead *);
 
 static short nfscberr_null[] = {
 	0,
@@ -749,8 +756,14 @@ nfscl_getcl(struct mount *mp, struct ucr
 		clp->nfsc_idlen = idlen;
 		LIST_INIT(&clp->nfsc_owner);
 		TAILQ_INIT(&clp->nfsc_deleg);
+		TAILQ_INIT(&clp->nfsc_layout);
+		TAILQ_INIT(&clp->nfsc_devinfo);
 		for (i = 0; i < NFSCLDELEGHASHSIZE; i++)
 			LIST_INIT(&clp->nfsc_deleghash[i]);
+		for (i = 0; i < NFSCLLAYOUTHASHSIZE; i++)
+			LIST_INIT(&clp->nfsc_layouthash[i]);
+		for (i = 0; i < NFSCLDEVINFOHASHSIZE; i++)
+			LIST_INIT(&clp->nfsc_devinfohash[i]);
 		clp->nfsc_flags = NFSCLFLAGS_INITED;
 		clp->nfsc_clientidrev = 1;
 		clp->nfsc_cbident = nfscl_nextcbident();
@@ -4373,3 +4386,200 @@ nfscl_errmap(struct nfsrv_descript *nd)
 	return (txdr_unsigned(*defaulterrp));
 }
 
+/*
+ * Called to find/add a layout to a client.
+ */
+APPLESTATIC int
+nfscl_layout(struct nfsmount *nmp, u_int8_t *fhp, int fhlen,
+    nfsv4stateid_t *stateidp, int retonclose,
+    struct nfsclflayouthead *fhlp, struct nfscllayout **lypp,
+    struct ucred *cred, NFSPROC_T *p)
+{
+	struct nfsclclient *clp;
+	struct nfscllayout *lyp, *tlyp;
+
+	*lypp = NULL;
+	tlyp = malloc(sizeof(*tlyp) + fhlen - 1, M_NFSLAYOUT, M_WAITOK);
+
+	NFSLOCKCLSTATE();
+	clp = nmp->nm_clp;
+	if (clp == NULL) {
+		NFSUNLOCKCLSTATE();
+		free(tlyp, M_NFSLAYOUT);
+		return (EPERM);
+	}
+	lyp = nfscl_findlayout(clp, fhp, fhlen);
+	if (lyp == NULL) {
+		lyp = tlyp;
+		tlyp = NULL;
+		lyp->nfsly_stateid.seqid = stateidp->seqid;
+		lyp->nfsly_stateid.other[0] = stateidp->other[0];
+		lyp->nfsly_stateid.other[1] = stateidp->other[1];
+		lyp->nfsly_stateid.other[2] = stateidp->other[2];
+		LIST_INIT(&lyp->nfsly_flay);
+		lyp->nfsly_clp = clp;
+		lyp->nfsly_retonclose = retonclose;
+		lyp->nfsly_refcnt = 1;	/* Return with a reference cnt. */
+		lyp->nfsly_fhlen = fhlen;
+		NFSBCOPY(fhp, lyp->nfsly_fh, fhlen);
+		TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list);
+		LIST_INSERT_HEAD(NFSCLLAYOUTHASH(clp, fhp, fhlen), lyp,
+		    nfsly_hash);
+#ifdef notyet
+		lyp->nfsly_timestamp = NFSD_MONOSEC + 120;
+#endif
+		nfscl_layoutcnt++;
+	} else {
+		lyp->nfsly_refcnt++;
+		TAILQ_REMOVE(&clp->nfsc_layout, lyp, nfsly_list);
+		TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list);
+	}
+
+	/* Merge the new list of File Layouts into the list. */
+	nfscl_mergeflayouts(&lyp->nfsly_flay, fhlp);
+	NFSUNLOCKCLSTATE();
+	if (tlyp != NULL)
+		free(tlyp, M_NFSLAYOUT);
+	*lypp = lyp;
+	return (0);
+}
+
+/*
+ * Search for a layout by MDS file handle. If one is found, lock it it and
+ * return a pointer to it.
+ */
+struct nfscllayout *
+nfscl_getlayout(struct nfsmount *nmp, uint8_t *fhp, int fhlen)
+{
+	struct nfsclclient *clp;
+	struct nfscllayout *lyp;
+
+	NFSLOCKCLSTATE();
+	clp = nmp->nm_clp;
+	if (clp == NULL) {
+		NFSUNLOCKCLSTATE();
+		return (NULL);
+	}
+	lyp = nfscl_findlayout(clp, fhp, fhlen);
+	if (lyp != NULL) {
+		lyp->nfsly_refcnt++;
+		TAILQ_REMOVE(&clp->nfsc_layout, lyp, nfsly_list);
+		TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list);
+	}
+	NFSUNLOCKCLSTATE();
+	return (lyp);
+}
+
+/*
+ * Dereference a layout.
+ */
+void
+nfscl_rellayout(struct nfscllayout *lyp)
+{
+
+	NFSLOCKCLSTATE();
+	lyp->nfsly_refcnt--;
+	if (lyp->nfsly_refcnt == 0)
+		wakeup(&lyp->nfsly_refcnt);
+	NFSUNLOCKCLSTATE();
+}
+
+/*
+ * Dereference a devinfo structure.
+ */
+void
+nfscl_reldevinfo(struct nfscldevinfo *dip)
+{
+
+	NFSLOCKCLSTATE();
+	dip->nfsdi_refcnt--;
+	if (dip->nfsdi_refcnt == 0)
+		wakeup(&dip->nfsdi_refcnt);
+	NFSUNLOCKCLSTATE();
+}
+
+/*
+ * Find a layout for this file handle. Return NULL upon failure.
+ */
+static struct nfscllayout *
+nfscl_findlayout(struct nfsclclient *clp, u_int8_t *fhp, int fhlen)
+{
+	struct nfscllayout *lyp;
+
+	LIST_FOREACH(lyp, NFSCLLAYOUTHASH(clp, fhp, fhlen), nfsly_hash)
+		if (lyp->nfsly_fhlen == fhlen &&
+		    !NFSBCMP(lyp->nfsly_fh, fhp, fhlen))
+			break;
+	return (lyp);
+}
+
+/*
+ * Find a devinfo for this deviceid. Return NULL upon failure.
+ */
+static struct nfscldevinfo *
+nfscl_finddevinfo(struct nfsclclient *clp, uint8_t *deviceid)
+{
+	struct nfscldevinfo *dip;
+
+	LIST_FOREACH(dip, NFSCLDEVINFOHASH(clp, deviceid), nfsdi_hash)
+		if (NFSBCMP(dip->nfsdi_deviceid, deviceid, NFSX_V4DEVICEID)
+		    == 0)
+			break;
+	return (dip);
+}
+
+/*
+ * Merge the new file layout list into the main one, maintaining it in
+ * increasing offset order.
+ */
+static void
+nfscl_mergeflayouts(struct nfsclflayouthead *fhlp,
+    struct nfsclflayouthead *newfhlp)
+{
+	struct nfsclflayout *flp, *nflp, *prevflp, *tflp;
+
+	flp = LIST_FIRST(fhlp);
+	prevflp = NULL;
+	LIST_FOREACH_SAFE(nflp, newfhlp, nfsfl_list, tflp) {
+		while (flp != NULL && flp->nfsfl_off < nflp->nfsfl_off) {
+			prevflp = flp;
+			flp = LIST_NEXT(flp, nfsfl_list);
+		}
+		if (prevflp == NULL)
+			LIST_INSERT_HEAD(fhlp, nflp, nfsfl_list);
+		else
+			LIST_INSERT_AFTER(prevflp, nflp, nfsfl_list);
+		prevflp = nflp;
+	}
+}
+
+/*
+ * Add this nfscldevinfo to the client, if it doesn't already exist.
+ * This function consumes the structure pointed at by dip.
+ */
+APPLESTATIC void
+nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip)
+{
+	struct nfsclclient *clp;
+	struct nfscldevinfo *tdip;
+
+	NFSLOCKCLSTATE();
+	clp = nmp->nm_clp;
+	if (clp == NULL) {
+		NFSUNLOCKCLSTATE();
+		free(dip, M_NFSDEVINFO);
+		return;
+	}
+	tdip = nfscl_finddevinfo(clp, dip->nfsdi_deviceid);
+	if (tdip != NULL) {
+		nfscl_reldevinfo(tdip);
+		NFSUNLOCKCLSTATE();
+		free(dip, M_NFSDEVINFO);
+		return;
+	}
+	TAILQ_INSERT_HEAD(&clp->nfsc_devinfo, dip, nfsdi_list);
+	LIST_INSERT_HEAD(NFSCLDEVINFOHASH(clp, dip->nfsdi_deviceid), dip,
+	    nfsdi_hash);
+	NFSUNLOCKCLSTATE();
+}
+



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