From owner-svn-src-projects@FreeBSD.ORG Sat Aug 25 23:03:46 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0A2041065670; Sat, 25 Aug 2012 23:03:46 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E79588FC20; Sat, 25 Aug 2012 23:03:45 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q7PN3j31010473; Sat, 25 Aug 2012 23:03:45 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q7PN3jcN010463; Sat, 25 Aug 2012 23:03:45 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201208252303.q7PN3jcN010463@svn.freebsd.org> From: Rick Macklem Date: Sat, 25 Aug 2012 23:03:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r239694 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Aug 2012 23:03:46 -0000 Author: rmacklem Date: Sat Aug 25 23:03:45 2012 New Revision: 239694 URL: http://svn.freebsd.org/changeset/base/239694 Log: Add support for segmented file layouts to PNFS for the NFSv4.1 client. Also fix up debug printfs by making them controlable via the sysctl vfs.nfs.debuglevel. This completes all changes for the NFSv4.1 client needed as a result of testing at the recent Bakeathon. 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/nfscl.h projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clkrpc.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/nfs_clvnops.c Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c Sat Aug 25 23:03:45 2012 (r239694) @@ -94,6 +94,7 @@ extern struct nfsreqhead nfsd_reqq; extern int nfscl_ticks; extern void (*ncl_call_invalcaches)(struct vnode *); extern int nfs_numnfscbd; +extern int nfscl_debuglevel; SVCPOOL *nfscbd_pool; static int nfsrv_gsscallbackson = 0; @@ -805,7 +806,9 @@ tryagain: */ NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); nd->nd_repstat = fxdr_unsigned(u_int32_t, *tl); -if (nd->nd_repstat >= 10000) printf("proc=%d reps=%d\n",nd->nd_procnum,nd->nd_repstat); + if (nd->nd_repstat >= 10000) + NFSCL_DEBUG(1, "proc=%d reps=%d\n", (int)nd->nd_procnum, + (int)nd->nd_repstat); /* * Get rid of the tag, return count and SEQUENCE result for @@ -821,11 +824,13 @@ if (nd->nd_repstat >= 10000) printf("pro opcnt = fxdr_unsigned(int, *tl++); i = fxdr_unsigned(int, *tl++); j = fxdr_unsigned(int, *tl); -if (j >= 10000) printf("fop=%d fst=%d\n",i,j); + if (j >= 10000) + NFSCL_DEBUG(1, "fop=%d fst=%d\n", i, j); /* * If the first op is Sequence, free up the slot. */ -if (nmp != NULL && i == NFSV4OP_SEQUENCE && j != 0) printf("failed seq=%d\n", j); + if (nmp != NULL && i == NFSV4OP_SEQUENCE && j != 0) + NFSCL_DEBUG(1, "failed seq=%d\n", j); if (nmp != NULL && i == NFSV4OP_SEQUENCE && j == 0) { NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED); @@ -843,7 +848,6 @@ if (nmp != NULL && i == NFSV4OP_SEQUENCE sep->nfsess_foreslots = (retval < 64) ? (retval + 1) : 64; 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) { @@ -910,12 +914,15 @@ if (nmp != NULL && i == NFSV4OP_SEQUENCE /* * If this op is Putfh, throw its results away. */ -if (j >= 10000) printf("nop=%d nst=%d\n",i,j); + if (j >= 10000) + NFSCL_DEBUG(1, "nop=%d nst=%d\n", i, j); if (nmp != NULL && i == NFSV4OP_PUTFH && j == 0) { NFSM_DISSECT(tl,u_int32_t *,2 * NFSX_UNSIGNED); i = fxdr_unsigned(int, *tl++); j = fxdr_unsigned(int, *tl); -if (j >= 10000) printf("n2op=%d n2st=%d\n",i,j); + if (j >= 10000) + NFSCL_DEBUG(1, "n2op=%d n2st=%d\n", i, + j); /* * All Compounds that do an Op that must * be in sequence consist of NFSV4OP_PUTFH Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c Sat Aug 25 23:03:45 2012 (r239694) @@ -61,6 +61,7 @@ struct mount nfsv4root_mnt; int newnfs_numnfsd = 0; struct nfsstats newnfsstats; int nfs_numnfscbd = 0; +int nfscl_debuglevel = 0; char nfsv4_callbackaddr[INET6_ADDRSTRLEN]; struct callout newnfsd_callout; void (*nfsd_call_servertimer)(void) = NULL; @@ -77,6 +78,8 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_c SYSCTL_STRING(_vfs_nfs, OID_AUTO, callback_addr, CTLFLAG_RW, nfsv4_callbackaddr, sizeof(nfsv4_callbackaddr), "NFSv4 callback addr for server to use"); +SYSCTL_INT(_vfs_nfs, OID_AUTO, debuglevel, CTLFLAG_RW, &nfscl_debuglevel, + 0, "Debug level for newnfs client"); /* * Defines for malloc Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h Sat Aug 25 23:03:45 2012 (r239694) @@ -459,6 +459,8 @@ int nfsrpc_layoutreturn(struct nfsmount int nfsrpc_reclaimcomplete(struct nfsmount *, struct ucred *, NFSPROC_T *); int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t, struct ucred *, NFSPROC_T *); +int nfscl_findlayoutforio(struct nfscllayout *, uint64_t, uint32_t, + struct nfsclflayout **); void nfscl_freenfsclds(struct nfsclds *); /* nfs_clstate.c */ @@ -525,8 +527,8 @@ int nfscl_layout(struct nfsmount *, vnod int, struct nfsclflayouthead *, struct nfscllayout **, struct ucred *, NFSPROC_T *); struct nfscllayout *nfscl_getlayout(struct nfsclclient *, uint8_t *, int, - int *); -void nfscl_rellayout(struct nfscllayout *); + uint64_t, struct nfsclflayout **, int *); +void nfscl_rellayout(struct nfscllayout *, int); struct nfscldevinfo *nfscl_getdevinfo(struct nfsclclient *, uint8_t *, struct nfscldevinfo *); void nfscl_reldevinfo(struct nfscldevinfo *); Modified: projects/nfsv4.1-client/sys/fs/nfs/nfscl.h ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfscl.h Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfs/nfscl.h Sat Aug 25 23:03:45 2012 (r239694) @@ -68,4 +68,10 @@ struct nfsv4node { #define NFSSATTR_SIZENEG1 0x4 #define NFSSATTR_SIZERDEV 0x8 +/* Use this macro for debug printfs. */ +#define NFSCL_DEBUG(level, ...) do { \ + if (nfscl_debuglevel >= (level)) \ + printf(__VA_ARGS__); \ + } while (0) + #endif /* _NFS_NFSCL_H */ Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h Sat Aug 25 23:03:45 2012 (r239694) @@ -231,6 +231,7 @@ struct nfscllayout { TAILQ_ENTRY(nfscllayout) nfsly_list; LIST_ENTRY(nfscllayout) nfsly_hash; nfsv4stateid_t nfsly_stateid; + struct nfsv4lock nfsly_lock; uint64_t nfsly_filesid[2]; uint64_t nfsly_lastbyte; struct nfsclflayouthead nfsly_flayread; @@ -238,7 +239,6 @@ struct nfscllayout { struct nfsclrecalllayouthead nfsly_recall; time_t nfsly_timestamp; struct nfsclclient *nfsly_clp; - uint32_t nfsly_refcnt; uint16_t nfsly_flags; uint16_t nfsly_fhlen; uint8_t nfsly_fh[1]; Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clkrpc.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clkrpc.c Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clkrpc.c Sat Aug 25 23:03:45 2012 (r239694) @@ -51,6 +51,7 @@ static int nfs_cbproc(struct nfsrv_descr extern u_long sb_max_adj; extern int nfs_numnfscbd; +extern int nfscl_debuglevel; /* * NFS client system calls for handling callbacks. @@ -90,7 +91,7 @@ nfscb_program(struct svc_req *rqst, SVCX nd.nd_mreq = NULL; nd.nd_cred = NULL; -printf("cbproc=%d\n",nd.nd_procnum); + NFSCL_DEBUG(1, "cbproc=%d\n",nd.nd_procnum); if (nd.nd_procnum != NFSPROC_NULL) { if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { svcerr_weakauth(rqst); @@ -134,11 +135,10 @@ printf("cbproc=%d\n",nd.nd_procnum); svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); if (nd.nd_mreq != NULL) m_freem(nd.nd_mreq); - } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) { + } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) svcerr_systemerr(rqst); -} else { -printf("cbrep sent\n"); - } + else + NFSCL_DEBUG(1, "cbrep sent\n"); svc_freereq(rqst); } Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c Sat Aug 25 23:03:45 2012 (r239694) @@ -56,6 +56,7 @@ extern u_int32_t newnfs_false, newnfs_tr extern nfstype nfsv34_type[9]; extern int nfsrv_useacl; extern char nfsv4_callbackaddr[INET6_ADDRSTRLEN]; +extern int nfscl_debuglevel; NFSCLSTATEMUTEX; int nfstest_outofseq = 0; int nfscl_assumeposixlocks = 1; @@ -99,13 +100,11 @@ static int nfsrpc_locku(struct nfsrv_des static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *, struct acl *, nfsv4stateid_t *, void *); static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int, - uint32_t *, nfsv4stateid_t *, struct nfscllayout **, struct ucred *, - NFSPROC_T *); + uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **, + struct ucred *, 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 **); static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *, nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfsclflayout *, uint64_t, uint64_t, struct ucred *, NFSPROC_T *); @@ -828,7 +827,7 @@ nfsrpc_setclient(struct nfsmount *nmp, s if (NFSHASNFSV4N(nmp)) { error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sockreq, NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, &dsp, cred, p); -if (error) printf("exch=%d\n",error); + NFSCL_DEBUG(1, "aft exch=%d\n", error); if (error == 0) { error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess, &nmp->nm_sockreq, @@ -844,11 +843,11 @@ if (error) printf("exch=%d\n",error); NFSUNLOCKMNT(nmp); } else nfscl_freenfsclds(dsp); -if (error) printf("aft crs=%d\n",error); + NFSCL_DEBUG(1, "aft createsess=%d\n", error); } if (error == 0 && reclaim == 0) { error = nfsrpc_reclaimcomplete(nmp, cred, p); -if (error) printf("aft reclcom=%d\n",error); + NFSCL_DEBUG(1, "aft reclaimcomp=%d\n", error); if (error == NFSERR_COMPLETEALREADY || error == NFSERR_NOTSUPP) /* Ignore this error. */ @@ -4289,7 +4288,6 @@ nfsrpc_getdirpath(struct nfsmount *nmp, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); if (error) return (error); -printf("dirp ret=%d\n", nd->nd_repstat); if (nd->nd_repstat == 0) { NFSM_DISSECT(tl, u_int32_t *, (3 + 2 * cnt) * NFSX_UNSIGNED); tl += (2 + 2 * cnt); @@ -4452,14 +4450,13 @@ nfsrpc_exchangeid(struct nfsmount *nmp, nd->nd_flag |= ND_USEGSSNAME; 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); + NFSCL_DEBUG(1, "exchangeid err=%d reps=%d\n", error, + (int)nd->nd_repstat); 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 < 0 || len > NFSV4_OPAQUELIMIT) { error = NFSERR_BADXDR; goto nfsmout; @@ -4470,15 +4467,12 @@ printf("servlen=%d\n", len); 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 && NFSHASPNFSOPT(nmp)) { -printf("set PNFS\n"); + NFSCL_DEBUG(1, "set PNFS\n"); NFSLOCKMNT(nmp); nmp->nm_state |= NFSSTA_PNFS; NFSUNLOCKMNT(nmp); @@ -4489,7 +4483,6 @@ printf("set PNFS\n"); 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", @@ -4522,9 +4515,7 @@ 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) crflags |= NFSV4CRSESS_CONNBACKCHAN; @@ -4573,8 +4564,6 @@ printf("clseq0=0x%x\n",sequenceid); tl += NFSX_V4SESSIONID / NFSX_UNSIGNED; sep->nfsess_sequenceid = fxdr_unsigned(uint32_t, *tl++); crflags = fxdr_unsigned(uint32_t, *tl); -printf("clseq=0x%x\n",sep->nfsess_sequenceid); -printf("crfl=0x%x\n",crflags); if ((crflags & NFSV4CRSESS_PERSIST) != 0 && mds != 0) { NFSLOCKMNT(nmp); nmp->nm_state |= NFSSTA_SESSPERSIST; @@ -4583,23 +4572,20 @@ 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 += 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); + NFSCL_DEBUG(4, "fore slots=%d\n", (int)sep->nfsess_foreslots); irdcnt = fxdr_unsigned(int, *tl); - if (irdcnt > 0) { -printf("got an ird cnt=%d\n",irdcnt); + if (irdcnt > 0) NFSM_DISSECT(tl, uint32_t *, irdcnt * NFSX_UNSIGNED); - } /* and the back channel slot count. */ NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); tl += 5; sep->nfsess_backslots = fxdr_unsigned(uint16_t, *tl); -printf("back slots=%d\n", sep->nfsess_backslots); + NFSCL_DEBUG(4, "back slots=%d\n", (int)sep->nfsess_backslots); } error = nd->nd_repstat; nfsmout: @@ -4690,7 +4676,7 @@ nfsrpc_layoutget(struct nfsmount *nmp, u txdr_hyper(minlen, tl); tl += 2; *tl++ = txdr_unsigned(stateidp->seqid); -printf("layget seq=%d\n", stateidp->seqid); + NFSCL_DEBUG(4, "layget seq=%d\n", (int)stateidp->seqid); *tl++ = stateidp->other[0]; *tl++ = stateidp->other[1]; *tl++ = stateidp->other[2]; @@ -4707,12 +4693,13 @@ printf("layget seq=%d\n", stateidp->seqi else *retonclosep = 0; stateidp->seqid = fxdr_unsigned(uint32_t, *tl++); -printf("retoncls=%d stseq=%d\n", *retonclosep, stateidp->seqid); + NFSCL_DEBUG(4, "retoncls=%d stseq=%d\n", *retonclosep, + (int)stateidp->seqid); stateidp->other[0] = *tl++; stateidp->other[1] = *tl++; stateidp->other[2] = *tl++; cnt = fxdr_unsigned(int, *tl); -printf("layg cnt=%d\n", cnt); + NFSCL_DEBUG(4, "layg cnt=%d\n", cnt); if (cnt <= 0 || cnt > 10000) { /* Don't accept more than 10000 layouts in reply. */ error = NFSERR_BADXDR; @@ -4724,7 +4711,7 @@ printf("layg cnt=%d\n", cnt); 6 * NFSX_UNSIGNED + NFSX_V4DEVICEID); fhcnt = fxdr_unsigned(int, *(tl + 11 + NFSX_V4DEVICEID / NFSX_UNSIGNED)); -printf("fhcnt=%d\n", fhcnt); + NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt); if (fhcnt < 0 || fhcnt > 100) { /* Don't accept more than 100 file handles. */ error = NFSERR_BADXDR; @@ -4749,7 +4736,8 @@ printf("fhcnt=%d\n", fhcnt); flp->nfsfl_iomode = fxdr_unsigned(int, *tl++); if (gotiomode == -1) gotiomode = flp->nfsfl_iomode; -printf("layg reqiom=%d retiom=%d\n", iomode, flp->nfsfl_iomode); + NFSCL_DEBUG(4, "layg reqiom=%d retiom=%d\n", iomode, + (int)flp->nfsfl_iomode); if (fxdr_unsigned(int, *tl++) != NFSLAYOUT_NFSV4_1_FILES) { printf("NFSv4.1: got non-files layout\n"); @@ -4759,6 +4747,7 @@ printf("layg reqiom=%d retiom=%d\n", iom NFSBCOPY(++tl, flp->nfsfl_dev, NFSX_V4DEVICEID); tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); flp->nfsfl_util = fxdr_unsigned(uint32_t, *tl++); + NFSCL_DEBUG(4, "flutil=0x%x\n", flp->nfsfl_util); flp->nfsfl_stripe1 = fxdr_unsigned(uint32_t, *tl++); flp->nfsfl_patoff = fxdr_hyper(tl); tl += 2; if (fxdr_unsigned(int, *tl) != fhcnt) { @@ -4852,7 +4841,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); + NFSCL_DEBUG(4, "stripecnt=%d\n", stripecnt); if (stripecnt < 1 || stripecnt > 4096) { printf("NFS devinfo stripecnt %d: out of range\n", stripecnt); @@ -4861,7 +4850,7 @@ printf("stripecnt=%d\n", stripecnt); } NFSM_DISSECT(tl, uint32_t *, (stripecnt + 1) * NFSX_UNSIGNED); addrcnt = fxdr_unsigned(int, *(tl + stripecnt)); -printf("addrcnt=%d\n", addrcnt); + NFSCL_DEBUG(4, "addrcnt=%d\n", addrcnt); if (addrcnt < 1 || addrcnt > 128) { printf("NFS devinfo addrcnt %d: out of range\n", addrcnt); @@ -4875,7 +4864,7 @@ printf("addrcnt=%d\n", addrcnt); */ i = (stripecnt * sizeof(uint8_t)) / sizeof(struct nfsclds *) + 1; -printf("i=%d\n", i); + NFSCL_DEBUG(4, "stripeindices=%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); @@ -4885,7 +4874,7 @@ printf("i=%d\n", i); /* Fill in the stripe indices. */ for (i = 0; i < stripecnt; i++) { stripeindex = fxdr_unsigned(uint8_t, *tl++); -printf("stripeind=%d\n", stripeindex); + NFSCL_DEBUG(4, "stripeind=%d\n", stripeindex); if (stripeindex >= addrcnt) { printf("NFS devinfo stripeindex %d: too big\n", (int)stripeindex); @@ -4908,7 +4897,6 @@ printf("stripeind=%d\n", stripeindex); 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) { @@ -4936,7 +4924,6 @@ printf("dspp=%p pos=%d\n", dspp, pos); &dsp, p); if (error == 0) { *dspp = dsp; -printf("safill dsp=%p\n", dsp); if (ss.ss_family == nmp->nm_nam->sa_family) safilled = 2; @@ -5062,7 +5049,7 @@ nfsrpc_layoutreturn(struct nfsmount *nmp tl += 2; txdr_hyper(len, tl); tl += 2; -printf("layret stseq=%d\n", stateidp->seqid); + NFSCL_DEBUG(4, "layoutret stseq=%d\n", (int)stateidp->seqid); *tl++ = txdr_unsigned(stateidp->seqid); *tl++ = stateidp->other[0]; *tl++ = stateidp->other[1]; @@ -5105,60 +5092,82 @@ nfsmout: */ static int nfsrpc_getlayout(struct nfsmount *nmp, vnode_t vp, struct nfsfh *nfhp, - int iomode, uint32_t *notifybitsp, nfsv4stateid_t *stateidp, + int iomode, uint32_t *notifybitsp, nfsv4stateid_t *stateidp, uint64_t off, struct nfscllayout **lypp, struct ucred *cred, NFSPROC_T *p) { struct nfscllayout *lyp; - struct nfsclflayout *flp; + struct nfsclflayout *flp, *tflp; struct nfscldevinfo *dip; struct nfsclflayouthead flh; - int error = 0, layoutlen, recalled, retonclose; + int error = 0, islocked, layoutlen, recalled, retonclose; nfsv4stateid_t stateid; *lypp = NULL; + /* + * If lyp is returned non-NULL, there will be a refcnt (shared lock) + * on it, iff flp != NULL or a lock (exclusive lock) on it iff + * flp == NULL. + */ lyp = nfscl_getlayout(nmp->nm_clp, nfhp->nfh_fh, nfhp->nfh_len, - &recalled); - if (lyp == NULL) { + off, &flp, &recalled); + islocked = 0; + if (lyp == NULL || flp == NULL) { 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, layoutlen, - &stateid, &retonclose, &flh, cred, p, NULL); + if (lyp == NULL) { + 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, layoutlen, &stateid, &retonclose, + &flh, cred, p, NULL); + } else { + islocked = 1; + stateid.seqid = lyp->nfsly_stateid.seqid; + stateid.other[0] = lyp->nfsly_stateid.other[0]; + stateid.other[1] = lyp->nfsly_stateid.other[1]; + stateid.other[2] = lyp->nfsly_stateid.other[2]; + error = nfsrpc_layoutget(nmp, nfhp->nfh_fh, + nfhp->nfh_len, iomode, off, 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); + LIST_FOREACH(tflp, &flh, nfsfl_list) { + error = nfscl_adddevinfo(nmp, NULL, tflp); if (error != 0) { error = nfsrpc_getdeviceinfo(nmp, - flp->nfsfl_dev, + tflp->nfsfl_dev, NFSLAYOUT_NFSV4_1_FILES, notifybitsp, &dip, cred, p); if (error != 0) break; - error = nfscl_adddevinfo(nmp, dip, flp); + error = nfscl_adddevinfo(nmp, dip, + tflp); if (error != 0) printf( "getlayout: cannot add\n"); } } - if (error == 0) + if (error == 0) { + /* + * nfscl_layout() always returns with the nfsly_lock + * set to a refcnt (shared lock). + */ error = nfscl_layout(nmp, vp, nfhp->nfh_fh, nfhp->nfh_len, &stateid, retonclose, &flh, &lyp, cred, p); - } - if (lyp != NULL) { - if (error == 0) - *lypp = lyp; - else - nfscl_rellayout(lyp); - } + if (error == 0) + *lypp = lyp; + } else if (islocked != 0) + nfsv4_unlock(&lyp->nfsly_lock, 0); + } else + *lypp = lyp; return (error); } @@ -5189,7 +5198,6 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru return (EPERM); if (ssp->ss_family == AF_INET) { ssd = (struct sockaddr_in *)ssp; -printf("ds addr=0x%x ", ssd->sin_addr.s_addr); NFSLOCKMNT(nmp); /* @@ -5199,8 +5207,6 @@ printf("ds addr=0x%x ", ssd->sin_addr.s_ * 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 && @@ -5209,7 +5215,7 @@ printf("\n"); (tdsp->nfsclds_flags & NFSCLDS_DS) != 0) { *dspp = tdsp; NFSUNLOCKMNT(nmp); -printf("fnd same addr\n"); + NFSCL_DEBUG(4, "fnd same addr\n"); return (0); } tdsp = TAILQ_NEXT(tdsp, nfsclds_list); @@ -5286,18 +5292,18 @@ printf("fnd same addr\n"); */ nrp->nr_cred = crhold(nmp->nm_sockreq.nr_cred); error = newnfs_connect(nmp, nrp, NULL, p, 0); -printf("ds conn=%d\n", error); + NFSCL_DEBUG(3, "DS connect=%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); + NFSCL_DEBUG(3, "DS exchangeid=%d\n", error); if (error == 0) { dsp->nfsclds_sockp = nrp; NFSLOCKMNT(nmp); retv = nfscl_getsameserver(nmp, dsp, &tdsp); -printf("getsame ret=%d\n", retv); + NFSCL_DEBUG(3, "getsame ret=%d\n", retv); if (retv == NFSDSP_USETHISSESSION) { NFSUNLOCKMNT(nmp); /* @@ -5316,7 +5322,7 @@ printf("getsame ret=%d\n", retv); NFSUNLOCKMNT(nmp); error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess, nrp, sequenceid, 0, nrp->nr_cred, p); -printf("dscrsess=%d\n", error); + NFSCL_DEBUG(3, "DS createsess=%d\n", error); } else { NFSFREECRED(nrp->nr_cred); NFSFREEMUTEX(&nrp->nr_mtx); @@ -5324,7 +5330,7 @@ printf("dscrsess=%d\n", error); free(nrp, M_NFSSOCKREQ); } if (error == 0) { -printf("add dssess\n"); + NFSCL_DEBUG(3, "add DS session\n"); /* * Put it at the end of the list. That way the list * is ordered by when the entry was added. This matters @@ -5412,15 +5418,24 @@ nfscl_doiods(vnode_t vp, struct uio *uio error = nfscl_getstateid(vp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len, rwaccess, 1, newcred, p, &stateid, &lckp); if (error != 0) { -if (error == 2) printf("rwacc=0x%x\n", rwaccess); NFSFREECRED(newcred); nfscl_relref(nmp); return (error); } /* Search for a layout for this file. */ + off = uiop->uio_offset; layp = nfscl_getlayout(nmp->nm_clp, np->n_fhp->nfh_fh, - np->n_fhp->nfh_len, &recalled); - if (layp == NULL) { + np->n_fhp->nfh_len, off, &rflp, &recalled); + if (layp == NULL || rflp == NULL) { + if (recalled != 0) { + NFSFREECRED(newcred); + nfscl_relref(nmp); + return (EIO); + } + if (layp != NULL) { + nfscl_rellayout(layp, (rflp == NULL) ? 1 : 0); + layp = NULL; + } /* Try and get a Layout, if it is supported. */ if (rwaccess == NFSV4OPEN_ACCESSWRITE || (np->n_flag & NWRITEOPENED) != 0) @@ -5428,7 +5443,7 @@ if (error == 2) printf("rwacc=0x%x\n", r else iolaymode = NFSLAYOUTIOMODE_READ; error = nfsrpc_getlayout(nmp, vp, np->n_fhp, iolaymode, - NULL, &stateid, &layp, newcred, p); + NULL, &stateid, off, &layp, newcred, p); if (error != 0) { NFSLOCKNODE(np); np->n_flag |= NNOLAYOUT; @@ -5437,7 +5452,7 @@ if (error == 2) printf("rwacc=0x%x\n", r nfscl_lockderef(lckp); NFSFREECRED(newcred); if (layp != NULL) - nfscl_rellayout(layp); + nfscl_rellayout(layp, 0); nfscl_relref(nmp); return (error); } @@ -5470,7 +5485,6 @@ if (error == 2) printf("rwacc=0x%x\n", r if (lastbyte > layp->nfsly_lastbyte) layp->nfsly_lastbyte = lastbyte; NFSUNLOCKCLSTATE(); -printf("lastb=%qd\n", layp->nfsly_lastbyte); } } else error = EIO; @@ -5481,7 +5495,7 @@ printf("lastb=%qd\n", layp->nfsly_lastby if (lckp != NULL) nfscl_lockderef(lckp); NFSFREECRED(newcred); - nfscl_rellayout(layp); + nfscl_rellayout(layp, 0); nfscl_relref(nmp); return (error); } @@ -5490,7 +5504,7 @@ printf("lastb=%qd\n", layp->nfsly_lastby * Find a file layout that will handle the first bytes of the requested * range and return the information from it needed to to the I/O operation. */ -static int +int nfscl_findlayoutforio(struct nfscllayout *lyp, uint64_t off, uint32_t rwaccess, struct nfsclflayout **retflpp) { @@ -5792,7 +5806,9 @@ nfscl_getsameserver(struct nfsmount *nmp dsp->nfsclds_servownlen != 0 && !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); + NFSCL_DEBUG(4, "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; Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c Sat Aug 25 23:01:57 2012 (r239693) +++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c Sat Aug 25 23:03:45 2012 (r239694) @@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$"); extern struct nfsstats newnfsstats; extern struct nfsreqhead nfsd_reqq; extern u_int32_t newnfs_false, newnfs_true; +extern int nfscl_debuglevel; NFSREQSPINLOCK; NFSCLSTATEMUTEX; int nfscl_inited = 0; @@ -2633,13 +2634,21 @@ tryagain2: /* * Wait for outstanding I/O ops to be done. */ - if (lyp->nfsly_refcnt > 0) { -printf("layrec io=%d\n", lyp->nfsly_refcnt); - (void)mtx_sleep(&lyp->nfsly_refcnt, - NFSCLSTATEMUTEXPTR, PZERO, "nfslyd", - 0); + if (lyp->nfsly_lock.nfslock_usecnt > 0 || + (lyp->nfsly_lock.nfslock_lock & + NFSV4LOCK_LOCK) != 0) { + lyp->nfsly_lock.nfslock_lock |= + NFSV4LOCK_WANTED; + (void)nfsmsleep(&lyp->nfsly_lock, + NFSCLSTATEMUTEXPTR, PZERO, "nfslyp", + NULL); goto tryagain2; } + /* Move the layout to the recall list. */ + TAILQ_REMOVE(&clp->nfsc_layout, lyp, + nfsly_list); + LIST_REMOVE(lyp, nfsly_hash); + TAILQ_INSERT_HEAD(&rlh, lyp, nfsly_list); /* Handle any layout commits. */ if (!NFSHASNOLAYOUTCOMMIT(clp->nfsc_nmp)) { @@ -2647,40 +2656,32 @@ printf("layrec io=%d\n", lyp->nfsly_refc nfsfl_list) { if ((flp->nfsfl_flags & NFSFL_WRITTEN) != 0) { - lyp->nfsly_refcnt++; flp->nfsfl_flags &= ~NFSFL_WRITTEN; NFSUNLOCKCLSTATE(); -printf("do layoutcommit\n"); + NFSCL_DEBUG(3, + "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; } } } - - /* Move the layout to the recall list. */ - TAILQ_REMOVE(&clp->nfsc_layout, lyp, - nfsly_list); - LIST_REMOVE(lyp, nfsly_hash); - TAILQ_INSERT_HEAD(&rlh, lyp, nfsly_list); } } + /* Now, look for stale layouts. */ lyp = TAILQ_LAST(&clp->nfsc_layout, nfscllayouthead); while (lyp != NULL) { nlyp = TAILQ_PREV(lyp, nfscllayouthead, nfsly_list); if (lyp->nfsly_timestamp < NFSD_MONOSEC && (lyp->nfsly_flags & NFSLY_RECALL) == 0 && - lyp->nfsly_refcnt == 0) { -printf("ret stale lay=%d\n", nfscl_layoutcnt); + lyp->nfsly_lock.nfslock_usecnt == 0 && + lyp->nfsly_lock.nfslock_lock == 0) { + NFSCL_DEBUG(4, "ret stale lay=%d\n", + nfscl_layoutcnt); recallp = malloc(sizeof(*recallp), M_NFSLAYRECALL, M_NOWAIT); if (recallp == NULL) @@ -2698,7 +2699,7 @@ printf("ret stale lay=%d\n", nfscl_layou LIST_FOREACH_SAFE(dip, &clp->nfsc_devinfo, nfsdi_list, ndip) { if (dip->nfsdi_layoutrefs == 0 && dip->nfsdi_refcnt == 0) { -printf("freeing devinfo\n"); + NFSCL_DEBUG(4, "freeing devinfo\n"); LIST_REMOVE(dip, nfsdi_list); nfscl_freedevinfo(dip); } @@ -2708,7 +2709,7 @@ printf("freeing devinfo\n"); /* Do layout return(s), as required. */ TAILQ_FOREACH_SAFE(lyp, &rlh, nfsly_list, nlyp) { TAILQ_REMOVE(&rlh, lyp, nfsly_list); -printf("ret layout\n"); + NFSCL_DEBUG(4, "ret layout\n"); nfscl_layoutreturn(clp->nfsc_nmp, lyp, cred, p); nfscl_freelayout(lyp); } @@ -3229,7 +3230,7 @@ nfscl_docb(struct nfsrv_descript *nd, NF newnfsstats.cbrpccnt[nd->nd_procnum]++; switch (op) { case NFSV4OP_CBGETATTR: -printf("cbgetattr\n"); + NFSCL_DEBUG(4, "cbgetattr\n"); mp = NULL; vp = NULL; error = nfsm_getfh(nd, &nfhp); @@ -3293,7 +3294,7 @@ printf("cbgetattr\n"); (uint64_t)0); break; case NFSV4OP_CBRECALL: -printf("cbrecall\n"); + NFSCL_DEBUG(4, "cbrecall\n"); NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED); stateid.seqid = *tl++; @@ -3329,7 +3330,7 @@ printf("cbrecall\n"); FREE((caddr_t)nfhp, M_NFSFH); break; case NFSV4OP_CBLAYOUTRECALL: -printf("cblayrec\n"); + NFSCL_DEBUG(4, "cblayrec\n"); nfhp = NULL; NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED); laytype = fxdr_unsigned(int, *tl++); @@ -3345,7 +3346,7 @@ printf("cblayrec\n"); error = NFSERR_NOMATCHLAYOUT; else if (recalltype == NFSLAYOUTRETURN_FILE) { error = nfsm_getfh(nd, &nfhp); -printf("retfile getfh=%d\n", error); + NFSCL_DEBUG(4, "retfile getfh=%d\n", error); if (error != 0) goto nfsmout; NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER + @@ -3361,12 +3362,13 @@ printf("retfile getfh=%d\n", error); if (error == 0) { NFSLOCKCLSTATE(); clp = nfscl_getclntsess(sessionid); -printf("cbly clp=%p\n", clp); + NFSCL_DEBUG(4, "cbly clp=%p\n", clp); if (clp != NULL) { lyp = nfscl_findlayout(clp, nfhp->nfh_fh, nfhp->nfh_len); -printf("cblyp=%p\n", lyp); + NFSCL_DEBUG(4, "cblyp=%p\n", + lyp); if (lyp != NULL && (lyp->nfsly_flags & NFSLY_FILES) != 0 && @@ -3381,7 +3383,9 @@ printf("cblyp=%p\n", lyp); recallp); recallp = NULL; wakeup(clp); -printf("aft layrec=%d\n", error); + NFSCL_DEBUG(4, + "aft layrcal=%d\n", + error); } else error = NFSERR_NOMATCHLAYOUT; @@ -3490,7 +3494,7 @@ printf("aft layrec=%d\n", error); if (error == 0) { gotseq_ok = 1; if (rep != NULL) { -printf("Got cbretry\n"); + NFSCL_DEBUG(4, "Got cbretry\n"); m_freem(nd->nd_mreq); nd->nd_mreq = rep; rep = NULL; @@ -3509,11 +3513,10 @@ printf("Got cbretry\n"); default: if (i == 0 && minorvers == NFSV41_MINORVERSION) error = NFSERR_OPNOTINSESS; - else -{ -printf("unsupp callback %d\n", op); + else { + NFSCL_DEBUG(1, "unsupp callback %d\n", op); error = NFSERR_NOTSUPP; -} + } break; }; if (error) { @@ -4678,6 +4681,10 @@ nfscl_errmap(struct nfsrv_descript *nd) /* * Called to find/add a layout to a client. + * This function returns the layout with a refcnt (shared lock) upon + * success (returns 0) or with no lock/refcnt on the layout when an + * error is returned. + * If a layout is passed in via lypp, it is locked (exclusively locked). */ APPLESTATIC int nfscl_layout(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, int fhlen, @@ -4689,50 +4696,76 @@ nfscl_layout(struct nfsmount *nmp, vnode struct nfscllayout *lyp, *tlyp; struct nfsclflayout *flp; struct nfsnode *np = VTONFS(vp); + mount_t mp; + int layout_passed_in; - *lypp = NULL; - tlyp = malloc(sizeof(*tlyp) + fhlen - 1, M_NFSLAYOUT, M_WAITOK); + mp = nmp->nm_mountp; + layout_passed_in = 1; + tlyp = NULL; + lyp = *lypp; + if (lyp == NULL) { + layout_passed_in = 0; + tlyp = malloc(sizeof(*tlyp) + fhlen - 1, M_NFSLAYOUT, + M_WAITOK | M_ZERO); + } NFSLOCKCLSTATE(); clp = nmp->nm_clp; if (clp == NULL) { + if (layout_passed_in != 0) + nfsv4_unlock(&lyp->nfsly_lock, 0); NFSUNLOCKCLSTATE(); - free(tlyp, M_NFSLAYOUT); + if (tlyp != NULL) + free(tlyp, M_NFSLAYOUT); return (EPERM); } - lyp = nfscl_findlayout(clp, fhp, fhlen); if (lyp == NULL) { - lyp = tlyp; - tlyp = NULL; + /* + * Although no lyp was passed in, another thread might have + * allocated one. If one is found, just increment it's ref + * count and return it. + */ + 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]; + lyp->nfsly_lastbyte = 0; + LIST_INIT(&lyp->nfsly_flayread); + LIST_INIT(&lyp->nfsly_flayrw); + LIST_INIT(&lyp->nfsly_recall); + lyp->nfsly_filesid[0] = np->n_vattr.na_filesid[0]; + lyp->nfsly_filesid[1] = np->n_vattr.na_filesid[1]; + lyp->nfsly_clp = clp; + lyp->nfsly_flags = (retonclose != 0) ? + (NFSLY_FILES | NFSLY_RETONCLOSE) : NFSLY_FILES; + 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); + lyp->nfsly_timestamp = NFSD_MONOSEC + 120; + nfscl_layoutcnt++; + } else { + if (retonclose != 0) + lyp->nfsly_flags |= NFSLY_RETONCLOSE; + TAILQ_REMOVE(&clp->nfsc_layout, lyp, nfsly_list); + TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list); + lyp->nfsly_timestamp = NFSD_MONOSEC + 120; + } + nfsv4_getref(&lyp->nfsly_lock, NULL, NFSCLSTATEMUTEXPTR, mp); + if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) { + NFSUNLOCKCLSTATE(); + if (tlyp != NULL) + free(tlyp, M_NFSLAYOUT); + return (EPERM); + } + *lypp = lyp; + } else 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]; - lyp->nfsly_lastbyte = 0; - LIST_INIT(&lyp->nfsly_flayread); - LIST_INIT(&lyp->nfsly_flayrw); - LIST_INIT(&lyp->nfsly_recall); - lyp->nfsly_filesid[0] = np->n_vattr.na_filesid[0]; - lyp->nfsly_filesid[1] = np->n_vattr.na_filesid[1]; - lyp->nfsly_clp = clp; - lyp->nfsly_flags = (retonclose != 0) ? - (NFSLY_FILES | NFSLY_RETONCLOSE) : NFSLY_FILES; - 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); - lyp->nfsly_timestamp = NFSD_MONOSEC + 120; - nfscl_layoutcnt++; - } else { - lyp->nfsly_refcnt++; - if (retonclose != 0) - lyp->nfsly_flags |= NFSLY_RETONCLOSE; - TAILQ_REMOVE(&clp->nfsc_layout, lyp, nfsly_list); - TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list); - lyp->nfsly_timestamp = NFSD_MONOSEC + 120; - } /* Merge the new list of File Layouts into the list. */ flp = LIST_FIRST(fhlp); @@ -4742,32 +4775,55 @@ nfscl_layout(struct nfsmount *nmp, vnode else nfscl_mergeflayouts(&lyp->nfsly_flayrw, fhlp); } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***