svn commit: r239694 - in projects/nfsv4.1-client/sys/fs: nfs
nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Sat Aug 25 23:03:46 UTC 2012
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 ***
More information about the svn-src-projects
mailing list