Move the NFSv4.1 client patches over from projects/nfsv4.1-client

to head. I don't think the NFS client behaviour will change unless
the new "minorversion=1" mount option is used. It includes basic
NFSv4.1 support plus support for pNFS using the Files Layout only.
All problems detecting during an NFSv4.1 Bakeathon testing event
in June 2012 have been resolved in this code and it has been tested
against the NFSv4.1 server available to me.
Although not reviewed, I believe that kib@ has looked at it.
This commit is contained in:
Rick Macklem 2012-12-08 22:52:39 +00:00
parent 839f11a4fe
commit 1f60bfd822
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=244042
22 changed files with 3978 additions and 386 deletions

View file

@ -50,6 +50,7 @@
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFSV4_CALLBACKTIMEO (2 * NFS_HZ) /* Timeout in ticks */
#define NFSV4_CALLBACKRETRY 5 /* Number of retries before failure */
#define NFSV4_CBSLOTS 8 /* Number of slots for session */
#define NFSV4_CBRETRYCNT 4 /* # of CBRecall retries upon err */
#define NFSV4_UPCALLTIMEO (15 * NFS_HZ) /* Timeout in ticks for upcalls */
/* to gssd or nfsuserd */
@ -100,6 +101,9 @@
#ifndef NFSCLDELEGHIGHWATER
#define NFSCLDELEGHIGHWATER 10000 /* limit for client delegations */
#endif
#ifndef NFSCLLAYOUTHIGHWATER
#define NFSCLLAYOUTHIGHWATER 10000 /* limit for client pNFS layouts */
#endif
#ifndef NFSNOOPEN /* Inactive open owner (sec) */
#define NFSNOOPEN 120
#endif
@ -529,6 +533,7 @@ struct nfsrv_descript {
nfsquad_t nd_clientid; /* Implied clientid */
int nd_gssnamelen; /* principal name length */
char *nd_gssname; /* principal name */
uint32_t *nd_slotseq; /* ptr to slot seq# in req */
};
#define nd_princlen nd_gssnamelen
@ -560,6 +565,8 @@ struct nfsrv_descript {
#define ND_EXGSSPRIVACY 0x00400000
#define ND_INCRSEQID 0x00800000
#define ND_NFSCL 0x01000000
#define ND_NFSV41 0x02000000
#define ND_HASSEQUENCE 0x04000000
/*
* ND_GSS should be the "or" of all GSS type authentications.
@ -572,6 +579,7 @@ struct nfsv4_opflag {
int savereply;
int modifyfs;
int lktype;
int needsseq;
};
/*
@ -645,6 +653,15 @@ struct nfsv4lock {
#define NFSACCCHK_VPNOTLOCKED 0
#define NFSACCCHK_VPISLOCKED 1
/*
* Slot for the NFSv4.1 Sequence Op.
*/
struct nfsslot {
int nfssl_inprog;
uint32_t nfssl_seq;
struct mbuf *nfssl_reply;
};
#endif /* _KERNEL */
#endif /* _NFS_NFS_H */

View file

@ -76,23 +76,27 @@ dtrace_nfsclient_nfs23_done_probe_func_t
/*
* Registered probes by RPC type.
*/
uint32_t nfscl_nfs2_start_probes[NFS_NPROCS + 1];
uint32_t nfscl_nfs2_done_probes[NFS_NPROCS + 1];
uint32_t nfscl_nfs2_start_probes[NFSV41_NPROCS + 1];
uint32_t nfscl_nfs2_done_probes[NFSV41_NPROCS + 1];
uint32_t nfscl_nfs3_start_probes[NFS_NPROCS + 1];
uint32_t nfscl_nfs3_done_probes[NFS_NPROCS + 1];
uint32_t nfscl_nfs3_start_probes[NFSV41_NPROCS + 1];
uint32_t nfscl_nfs3_done_probes[NFSV41_NPROCS + 1];
uint32_t nfscl_nfs4_start_probes[NFS_NPROCS + 1];
uint32_t nfscl_nfs4_done_probes[NFS_NPROCS + 1];
uint32_t nfscl_nfs4_start_probes[NFSV41_NPROCS + 1];
uint32_t nfscl_nfs4_done_probes[NFSV41_NPROCS + 1];
#endif
NFSSTATESPINLOCK;
NFSREQSPINLOCK;
NFSDLOCKMUTEX;
extern struct nfsstats newnfsstats;
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;
static int nfs_bufpackets = 4;
static int nfs_reconnects;
@ -167,6 +171,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
struct socket *so;
int one = 1, retries, error = 0;
struct thread *td = curthread;
SVCXPRT *xprt;
struct timeval timo;
/*
@ -277,6 +282,24 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
retries = nmp->nm_retry;
} else
retries = INT_MAX;
if (NFSHASNFSV4N(nmp)) {
/*
* Make sure the nfscbd_pool doesn't get destroyed
* while doing this.
*/
NFSD_LOCK();
if (nfs_numnfscbd > 0) {
nfs_numnfscbd++;
NFSD_UNLOCK();
xprt = svc_vc_create_backchannel(nfscbd_pool);
CLNT_CONTROL(client, CLSET_BACKCHANNEL, xprt);
NFSD_LOCK();
nfs_numnfscbd--;
if (nfs_numnfscbd == 0)
wakeup(&nfs_numnfscbd);
}
NFSD_UNLOCK();
}
} else {
/*
* Three cases:
@ -468,12 +491,13 @@ int
newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
struct nfsclient *clp, struct nfssockreq *nrp, vnode_t vp,
struct thread *td, struct ucred *cred, u_int32_t prog, u_int32_t vers,
u_char *retsum, int toplevel, u_int64_t *xidp)
u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *sep)
{
u_int32_t *tl;
u_int32_t retseq, retval, *tl;
time_t waituntil;
int i, j, set_sigset = 0, timeo;
int i = 0, j = 0, opcnt, set_sigset = 0, slot;
int trycnt, error = 0, usegssname = 0, secflavour = AUTH_SYS;
int freeslot, timeo;
u_int16_t procnum;
u_int trylater_delay = 1;
struct nfs_feedback_arg nf;
@ -670,7 +694,9 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
#endif
}
trycnt = 0;
freeslot = -1; /* Set to slot that needs to be free'd */
tryagain:
slot = -1; /* Slot that needs a sequence# increment. */
/*
* This timeout specifies when a new socket should be created,
* along with new xid values. For UDP, this should be done
@ -772,11 +798,66 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
nd->nd_repstat = 0;
if (nd->nd_procnum != NFSPROC_NULL) {
/* If sep == NULL, set it to the default in nmp. */
if (sep == NULL && nmp != NULL)
sep = NFSMNT_MDSSESSION(nmp);
/*
* and now the actual NFS xdr.
*/
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
nd->nd_repstat = fxdr_unsigned(u_int32_t, *tl);
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
* NFSv4.
*/
if ((nd->nd_flag & ND_NFSV4) != 0) {
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
i = fxdr_unsigned(int, *tl);
error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
if (error)
goto nfsmout;
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
opcnt = fxdr_unsigned(int, *tl++);
i = fxdr_unsigned(int, *tl++);
j = fxdr_unsigned(int, *tl);
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)
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);
mtx_lock(&sep->nfsess_mtx);
tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
retseq = fxdr_unsigned(uint32_t, *tl++);
slot = fxdr_unsigned(int, *tl++);
freeslot = slot;
if (retseq != sep->nfsess_slotseq[slot])
printf("retseq diff 0x%x\n", retseq);
retval = fxdr_unsigned(uint32_t, *++tl);
if ((retval + 1) < sep->nfsess_foreslots)
sep->nfsess_foreslots = (retval + 1);
else if ((retval + 1) > sep->nfsess_foreslots)
sep->nfsess_foreslots = (retval < 64) ?
(retval + 1) : 64;
mtx_unlock(&sep->nfsess_mtx);
/* Grab the op and status for the next one. */
if (opcnt > 1) {
NFSM_DISSECT(tl, uint32_t *,
2 * NFSX_UNSIGNED);
i = fxdr_unsigned(int, *tl++);
j = fxdr_unsigned(int, *tl);
}
}
}
if (nd->nd_repstat != 0) {
if (((nd->nd_repstat == NFSERR_DELAY ||
nd->nd_repstat == NFSERR_GRACE) &&
@ -784,7 +865,9 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
nd->nd_procnum != NFSPROC_DELEGRETURN &&
nd->nd_procnum != NFSPROC_SETATTR &&
nd->nd_procnum != NFSPROC_READ &&
nd->nd_procnum != NFSPROC_READDS &&
nd->nd_procnum != NFSPROC_WRITE &&
nd->nd_procnum != NFSPROC_WRITEDS &&
nd->nd_procnum != NFSPROC_OPEN &&
nd->nd_procnum != NFSPROC_CREATE &&
nd->nd_procnum != NFSPROC_OPENCONFIRM &&
@ -801,6 +884,13 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
while (NFSD_MONOSEC < waituntil)
(void) nfs_catnap(PZERO, 0, "nfstry");
trylater_delay *= 2;
if (slot != -1) {
mtx_lock(&sep->nfsess_mtx);
sep->nfsess_slotseq[slot]++;
*nd->nd_slotseq = txdr_unsigned(
sep->nfsess_slotseq[slot]);
mtx_unlock(&sep->nfsess_mtx);
}
m_freem(nd->nd_mrep);
nd->nd_mrep = NULL;
goto tryagain;
@ -817,34 +907,22 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
(*ncl_call_invalcaches)(vp);
}
}
/*
* Get rid of the tag, return count, and PUTFH result for V4.
*/
if (nd->nd_flag & ND_NFSV4) {
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
i = fxdr_unsigned(int, *tl);
error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
if (error)
goto nfsmout;
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
i = fxdr_unsigned(int, *++tl);
if ((nd->nd_flag & ND_NFSV4) != 0) {
/* Free the slot, as required. */
if (freeslot != -1)
nfsv4_freeslot(sep, freeslot);
/*
* If the first op's status is non-zero, mark that
* there is no more data to process.
* If this op is Putfh, throw its results away.
*/
if (*++tl)
nd->nd_flag |= ND_NOMOREDATA;
/*
* If the first op is Putfh, throw its results away
* and toss the op# and status for the first op.
*/
if (nmp != NULL && i == NFSV4OP_PUTFH && *tl == 0) {
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)
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
@ -867,19 +945,20 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
j != NFSERR_RESOURCE &&
j != NFSERR_NOFILEHANDLE)))
nd->nd_flag |= ND_INCRSEQID;
/*
* If the first op's status is non-zero, mark
* that there is no more data to process.
*/
if (j)
nd->nd_flag |= ND_NOMOREDATA;
}
/*
* If this op's status is non-zero, mark
* that there is no more data to process.
*/
if (j)
nd->nd_flag |= ND_NOMOREDATA;
/*
* If R_DONTRECOVER is set, replace the stale error
* reply, so that recovery isn't initiated.
*/
if ((nd->nd_repstat == NFSERR_STALECLIENTID ||
nd->nd_repstat == NFSERR_BADSESSION ||
nd->nd_repstat == NFSERR_STALESTATEID) &&
rep != NULL && (rep->r_flags & R_DONTRECOVER))
nd->nd_repstat = NFSERR_STALEDONTRECOVER;

View file

@ -106,6 +106,12 @@ MALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL diroffdiroff",
"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");
MALLOC_DEFINE(M_NEWNFSSOCKREQ, "NFSCL sockreq", "NFS Sock Req");
MALLOC_DEFINE(M_NEWNFSCLDS, "NFSCL session", "NFSv4.1 Session");
MALLOC_DEFINE(M_NEWNFSLAYRECALL, "NFSCL layrecall", "NFSv4.1 Layout Recall");
/*
* Definition of mutex locks.

View file

@ -85,47 +85,66 @@ NFSSOCKMUTEX;
* non-idempotent Ops.
* Define it here, since it is used by both the client and server.
*/
struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS] = {
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* undef */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* undef */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* undef */
{ 0, 1, 0, 0, LK_SHARED }, /* Access */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* Close */
{ 0, 2, 0, 1, LK_EXCLUSIVE }, /* Commit */
{ 1, 2, 1, 1, LK_EXCLUSIVE }, /* Create */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* Delegpurge */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* Delegreturn */
{ 0, 1, 0, 0, LK_SHARED }, /* Getattr */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* GetFH */
{ 2, 1, 1, 1, LK_EXCLUSIVE }, /* Link */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* Lock */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* LockT */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* LockU */
{ 1, 1, 0, 0, LK_EXCLUSIVE }, /* Lookup */
{ 1, 1, 0, 0, LK_EXCLUSIVE }, /* Lookupp */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* NVerify */
{ 1, 1, 0, 1, LK_EXCLUSIVE }, /* Open */
{ 1, 1, 0, 0, LK_EXCLUSIVE }, /* OpenAttr */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* OpenConfirm */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* OpenDowngrade */
{ 1, 0, 0, 0, LK_EXCLUSIVE }, /* PutFH */
{ 1, 0, 0, 0, LK_EXCLUSIVE }, /* PutPubFH */
{ 1, 0, 0, 0, LK_EXCLUSIVE }, /* PutRootFH */
{ 0, 1, 0, 0, LK_SHARED }, /* Read */
{ 0, 1, 0, 0, LK_SHARED }, /* Readdir */
{ 0, 1, 0, 0, LK_SHARED }, /* ReadLink */
{ 0, 2, 1, 1, LK_EXCLUSIVE }, /* Remove */
{ 2, 1, 1, 1, LK_EXCLUSIVE }, /* Rename */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* Renew */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* RestoreFH */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* SaveFH */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* SecInfo */
{ 0, 2, 1, 1, LK_EXCLUSIVE }, /* Setattr */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* SetClientID */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* SetClientIDConfirm */
{ 0, 1, 0, 0, LK_EXCLUSIVE }, /* Verify */
{ 0, 2, 1, 1, LK_EXCLUSIVE }, /* Write */
{ 0, 0, 0, 0, LK_EXCLUSIVE }, /* ReleaseLockOwner */
struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS] = {
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
{ 0, 1, 0, 0, LK_SHARED, 1 }, /* Access */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Close */
{ 0, 2, 0, 1, LK_EXCLUSIVE, 1 }, /* Commit */
{ 1, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Create */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Delegpurge */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Delegreturn */
{ 0, 1, 0, 0, LK_SHARED, 1 }, /* Getattr */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* GetFH */
{ 2, 1, 1, 1, LK_EXCLUSIVE, 1 }, /* Link */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Lock */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* LockT */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* LockU */
{ 1, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Lookup */
{ 1, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Lookupp */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* NVerify */
{ 1, 1, 0, 1, LK_EXCLUSIVE, 1 }, /* Open */
{ 1, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenAttr */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenConfirm */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenDowngrade */
{ 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutFH */
{ 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutPubFH */
{ 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutRootFH */
{ 0, 1, 0, 0, LK_SHARED, 1 }, /* Read */
{ 0, 1, 0, 0, LK_SHARED, 1 }, /* Readdir */
{ 0, 1, 0, 0, LK_SHARED, 1 }, /* ReadLink */
{ 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Remove */
{ 2, 1, 1, 1, LK_EXCLUSIVE, 1 }, /* Rename */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Renew */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* RestoreFH */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* SaveFH */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* SecInfo */
{ 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Setattr */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* SetClientID */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* SetClientIDConfirm */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Verify */
{ 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Write */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* ReleaseLockOwner */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Backchannel Ctrl */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Bind Conn to Sess */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Exchange ID */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Create Session */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Destroy Session */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Free StateID */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Dir Deleg */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Device Info */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Device List */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Commit */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Get */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Return */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Secinfo No name */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Sequence */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Set SSV */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Test StateID */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Want Delegation */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Destroy ClientID */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Reclaim Complete */
};
#endif /* !APPLEKEXT */
@ -147,9 +166,9 @@ static struct nfsuserlruhead nfsuserlruhead;
* marked 0 in this array, the code will still work, just not quite as
* efficiently.)
*/
static int nfs_bigreply[NFS_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0 };
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
/* local functions */
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
@ -1857,7 +1876,7 @@ nfsv4_getref(struct nfsv4lock *lp, int *isleptp, void *mutex,
if (isleptp)
*isleptp = 1;
(void) nfsmsleep(&lp->nfslock_lock, mutex,
PZERO - 1, "nfsv4lck", NULL);
PZERO - 1, "nfsv4gr", NULL);
}
if (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0)
return;
@ -3016,7 +3035,7 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name, NFSPROC_T *p)
(void) nfsm_strtom(nd, name, len);
}
error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL,
cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL);
cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL);
NFSFREECRED(cred);
if (!error) {
mbuf_freem(nd->nd_mrep);
@ -3510,3 +3529,240 @@ newnfs_sndunlock(int *flagp)
NFSUNLOCKSOCK();
}
APPLESTATIC int
nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_storage *sa,
int *isudp)
{
struct sockaddr_in *sad;
struct sockaddr_in6 *sad6;
struct in_addr saddr;
uint32_t portnum, *tl;
int af = 0, i, j, k;
char addr[64], protocol[5], *cp;
int cantparse = 0, error = 0;
uint16_t portv;
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
i = fxdr_unsigned(int, *tl);
if (i >= 3 && i <= 4) {
error = nfsrv_mtostr(nd, protocol, i);
if (error)
goto nfsmout;
if (strcmp(protocol, "tcp") == 0) {
af = AF_INET;
*isudp = 0;
} else if (strcmp(protocol, "udp") == 0) {
af = AF_INET;
*isudp = 1;
} else if (strcmp(protocol, "tcp6") == 0) {
af = AF_INET6;
*isudp = 0;
} else if (strcmp(protocol, "udp6") == 0) {
af = AF_INET6;
*isudp = 1;
} else
cantparse = 1;
} else {
cantparse = 1;
if (i > 0) {
error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
if (error)
goto nfsmout;
}
}
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
i = fxdr_unsigned(int, *tl);
if (i < 0) {
error = NFSERR_BADXDR;
goto nfsmout;
} else if (cantparse == 0 && i >= 11 && i < 64) {
/*
* The shortest address is 11chars and the longest is < 64.
*/
error = nfsrv_mtostr(nd, addr, i);
if (error)
goto nfsmout;
/* Find the port# at the end and extract that. */
i = strlen(addr);
k = 0;
cp = &addr[i - 1];
/* Count back two '.'s from end to get port# field. */
for (j = 0; j < i; j++) {
if (*cp == '.') {
k++;
if (k == 2)
break;
}
cp--;
}
if (k == 2) {
/*
* The NFSv4 port# is appended as .N.N, where N is
* a decimal # in the range 0-255, just like an inet4
* address. Cheat and use inet_aton(), which will
* return a Class A address and then shift the high
* order 8bits over to convert it to the port#.
*/
*cp++ = '\0';
if (inet_aton(cp, &saddr) == 1) {
portnum = ntohl(saddr.s_addr);
portv = (uint16_t)((portnum >> 16) |
(portnum & 0xff));
} else
cantparse = 1;
} else
cantparse = 1;
if (cantparse == 0) {
if (af == AF_INET) {
sad = (struct sockaddr_in *)sa;
if (inet_pton(af, addr, &sad->sin_addr) == 1) {
sad->sin_len = sizeof(*sad);
sad->sin_family = AF_INET;
sad->sin_port = htons(portv);
return (0);
}
} else {
sad6 = (struct sockaddr_in6 *)sa;
if (inet_pton(af, addr, &sad6->sin6_addr)
== 1) {
sad6->sin6_len = sizeof(*sad6);
sad6->sin6_family = AF_INET6;
sad6->sin6_port = htons(portv);
return (0);
}
}
}
} else {
if (i > 0) {
error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
if (error)
goto nfsmout;
}
}
error = EPERM;
nfsmout:
return (error);
}
/*
* Handle an NFSv4.1 Sequence request for the session.
*/
int
nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
struct nfsslot *slots, struct mbuf **reply, uint16_t maxslot)
{
int error;
error = 0;
*reply = NULL;
if (slotid > maxslot)
return (NFSERR_BADSLOT);
if (seqid == slots[slotid].nfssl_seq) {
/* A retry. */
if (slots[slotid].nfssl_inprog != 0)
error = NFSERR_DELAY;
else if (slots[slotid].nfssl_reply != NULL) {
*reply = slots[slotid].nfssl_reply;
slots[slotid].nfssl_reply = NULL;
slots[slotid].nfssl_inprog = 1;
} else
error = NFSERR_SEQMISORDERED;
} else if ((slots[slotid].nfssl_seq + 1) == seqid) {
m_freem(slots[slotid].nfssl_reply);
slots[slotid].nfssl_reply = NULL;
slots[slotid].nfssl_inprog = 1;
slots[slotid].nfssl_seq++;
} else
error = NFSERR_SEQMISORDERED;
return (error);
}
/*
* Cache this reply for the slot.
*/
void
nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, struct mbuf *rep)
{
slots[slotid].nfssl_reply = rep;
slots[slotid].nfssl_inprog = 0;
}
/*
* Generate the xdr for an NFSv4.1 Sequence Operation.
*/
APPLESTATIC void
nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep,
int dont_replycache)
{
uint32_t *tl, slotseq = 0;
int i, maxslot, slotpos;
uint64_t bitval;
uint8_t sessionid[NFSX_V4SESSIONID];
/* Find an unused slot. */
slotpos = -1;
maxslot = -1;
mtx_lock(&sep->nfsess_mtx);
do {
bitval = 1;
for (i = 0; i < sep->nfsess_foreslots; i++) {
if ((bitval & sep->nfsess_slots) == 0) {
slotpos = i;
sep->nfsess_slots |= bitval;
sep->nfsess_slotseq[i]++;
slotseq = sep->nfsess_slotseq[i];
break;
}
bitval <<= 1;
}
if (slotpos == -1)
(void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx,
PZERO, "nfsclseq", 0);
} while (slotpos == -1);
/* Now, find the highest slot in use. (nfsc_slots is 64bits) */
bitval = 1;
for (i = 0; i < 64; i++) {
if ((bitval & sep->nfsess_slots) != 0)
maxslot = i;
bitval <<= 1;
}
bcopy(sep->nfsess_sessionid, sessionid, NFSX_V4SESSIONID);
mtx_unlock(&sep->nfsess_mtx);
KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
/* Build the Sequence arguments. */
NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
bcopy(sessionid, tl, NFSX_V4SESSIONID);
tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
nd->nd_slotseq = tl;
*tl++ = txdr_unsigned(slotseq);
*tl++ = txdr_unsigned(slotpos);
*tl++ = txdr_unsigned(maxslot);
if (dont_replycache == 0)
*tl = newnfs_true;
else
*tl = newnfs_false;
nd->nd_flag |= ND_HASSEQUENCE;
}
/*
* Free a session slot.
*/
APPLESTATIC void
nfsv4_freeslot(struct nfsclsession *sep, int slot)
{
uint64_t bitval;
bitval = 1;
if (slot > 0)
bitval <<= slot;
mtx_lock(&sep->nfsess_mtx);
if ((bitval & sep->nfsess_slots) == 0)
printf("freeing free slot!!\n");
sep->nfsess_slots &= ~bitval;
wakeup(&sep->nfsess_slots);
mtx_unlock(&sep->nfsess_mtx);
}

View file

@ -69,9 +69,12 @@ struct nfsclowner;
struct nfsclopen;
struct nfsclopenhead;
struct nfsclclient;
struct nfsclsession;
struct nfscllockowner;
struct nfscllock;
struct nfscldeleg;
struct nfscllayout;
struct nfscldevinfo;
struct nfsv4lock;
struct nfsvattr;
struct nfs_vattr;
@ -257,11 +260,18 @@ int nfsrv_mtostr(struct nfsrv_descript *, char *, int);
int nfsrv_checkutf8(u_int8_t *, int);
int newnfs_sndlock(int *);
void newnfs_sndunlock(int *);
int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_storage *,
int *);
int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,
struct mbuf **, uint16_t);
void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, struct mbuf *);
void nfsv4_setsequence(struct nfsrv_descript *, struct nfsclsession *, int);
void nfsv4_freeslot(struct nfsclsession *, int);
/* nfs_clcomsubs.c */
void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);
void nfscl_reqstart(struct nfsrv_descript *, int, struct nfsmount *,
u_int8_t *, int, u_int32_t **);
u_int8_t *, int, u_int32_t **, struct nfsclsession *);
nfsuint64 *nfscl_getcookie(struct nfsnode *, off_t off, int);
void nfscl_fillsattr(struct nfsrv_descript *, struct vattr *,
vnode_t, int, u_int32_t);
@ -360,12 +370,12 @@ int nfsrpc_closerpc(struct nfsrv_descript *, struct nfsmount *,
struct nfsclopen *, struct ucred *, NFSPROC_T *, int);
int nfsrpc_openconfirm(vnode_t, u_int8_t *, int, struct nfsclopen *,
struct ucred *, NFSPROC_T *);
int nfsrpc_setclient(struct nfsmount *, struct nfsclclient *,
int nfsrpc_setclient(struct nfsmount *, struct nfsclclient *, int,
struct ucred *, NFSPROC_T *);
int nfsrpc_getattr(vnode_t, struct ucred *, NFSPROC_T *,
struct nfsvattr *, void *);
int nfsrpc_getattrnovp(struct nfsmount *, u_int8_t *, int, int,
struct ucred *, NFSPROC_T *, struct nfsvattr *, u_int64_t *);
struct ucred *, NFSPROC_T *, struct nfsvattr *, u_int64_t *, uint32_t *);
int nfsrpc_setattr(vnode_t, struct vattr *, NFSACL_T *, struct ucred *,
NFSPROC_T *, struct nfsvattr *, int *, void *);
int nfsrpc_lookup(vnode_t, char *, int, struct ucred *, NFSPROC_T *,
@ -404,7 +414,7 @@ int nfsrpc_readdir(vnode_t, struct uio *, nfsuint64 *, struct ucred *,
int nfsrpc_readdirplus(vnode_t, struct uio *, nfsuint64 *,
struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, int *, void *);
int nfsrpc_commit(vnode_t, u_quad_t, int, struct ucred *,
NFSPROC_T *, u_char *, struct nfsvattr *, int *, void *);
NFSPROC_T *, struct nfsvattr *, int *, void *);
int nfsrpc_advlock(vnode_t, off_t, int, struct flock *, int,
struct ucred *, NFSPROC_T *, void *, int);
int nfsrpc_lockt(struct nfsrv_descript *, vnode_t,
@ -419,7 +429,7 @@ int nfsrpc_fsinfo(vnode_t, struct nfsfsinfo *, struct ucred *,
NFSPROC_T *, struct nfsvattr *, int *, void *);
int nfsrpc_pathconf(vnode_t, struct nfsv3_pathconf *,
struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, void *);
int nfsrpc_renew(struct nfsclclient *, struct ucred *,
int nfsrpc_renew(struct nfsclclient *, struct nfsclds *, struct ucred *,
NFSPROC_T *);
int nfsrpc_rellockown(struct nfsmount *, struct nfscllockowner *, uint8_t *,
int, struct ucred *, NFSPROC_T *);
@ -429,16 +439,42 @@ int nfsrpc_delegreturn(struct nfscldeleg *, struct ucred *,
struct nfsmount *, NFSPROC_T *, int);
int nfsrpc_getacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *, void *);
int nfsrpc_setacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *, void *);
int nfsrpc_exchangeid(struct nfsmount *, struct nfsclclient *,
struct nfssockreq *, uint32_t, struct nfsclds **, struct ucred *,
NFSPROC_T *);
int nfsrpc_createsession(struct nfsmount *, struct nfsclsession *,
struct nfssockreq *, uint32_t, int, struct ucred *, NFSPROC_T *);
int nfsrpc_destroysession(struct nfsmount *, struct nfsclclient *,
struct ucred *, NFSPROC_T *);
int nfsrpc_destroyclient(struct nfsmount *, struct nfsclclient *,
struct ucred *, NFSPROC_T *);
int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t, uint64_t,
uint64_t, int, nfsv4stateid_t *, int *, struct nfsclflayouthead *,
struct ucred *, NFSPROC_T *, void *);
int nfsrpc_getdeviceinfo(struct nfsmount *, uint8_t *, int, uint32_t *,
struct nfscldevinfo **, struct ucred *, NFSPROC_T *);
int nfsrpc_layoutcommit(struct nfsmount *, uint8_t *, int, int,
uint64_t, uint64_t, uint64_t, nfsv4stateid_t *, int, int, uint8_t *,
struct ucred *, NFSPROC_T *, void *);
int nfsrpc_layoutreturn(struct nfsmount *, uint8_t *, int, int, int, uint32_t,
int, uint64_t, uint64_t, nfsv4stateid_t *, int, uint32_t *, struct ucred *,
NFSPROC_T *, void *);
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 */
int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int,
struct ucred *, NFSPROC_T *, struct nfsclowner **, struct nfsclopen **,
int *, int *, int);
int nfscl_getstateid(vnode_t, u_int8_t *, int, u_int32_t, struct ucred *,
int nfscl_getstateid(vnode_t, u_int8_t *, int, u_int32_t, int, struct ucred *,
NFSPROC_T *, nfsv4stateid_t *, void **);
void nfscl_ownerrelease(struct nfsclowner *, int, int, int);
void nfscl_openrelease(struct nfsclopen *, int, int);
int nfscl_getcl(vnode_t, struct ucred *, NFSPROC_T *,
int nfscl_getcl(struct mount *, struct ucred *, NFSPROC_T *, int,
struct nfsclclient **);
struct nfsclclient *nfscl_findcl(struct nfsmount *);
void nfscl_clientrelease(struct nfsclclient *);
@ -490,6 +526,21 @@ void nfscl_deleggetmodtime(vnode_t, struct timespec *);
int nfscl_tryclose(struct nfsclopen *, struct ucred *,
struct nfsmount *, NFSPROC_T *);
void nfscl_cleanup(NFSPROC_T *);
int nfscl_layout(struct nfsmount *, vnode_t, u_int8_t *, int, nfsv4stateid_t *,
int, struct nfsclflayouthead *, struct nfscllayout **, struct ucred *,
NFSPROC_T *);
struct nfscllayout *nfscl_getlayout(struct nfsclclient *, uint8_t *, int,
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 *);
int nfscl_adddevinfo(struct nfsmount *, struct nfscldevinfo *,
struct nfsclflayout *);
void nfscl_freelayout(struct nfscllayout *);
void nfscl_freeflayout(struct nfsclflayout *);
void nfscl_freedevinfo(struct nfscldevinfo *);
int nfscl_layoutcommit(vnode_t, NFSPROC_T *);
/* nfs_clport.c */
int nfscl_nget(mount_t, vnode_t, struct nfsfh *,
@ -588,7 +639,8 @@ void newnfs_restore_sigmask(struct thread *, sigset_t *);
int newnfs_msleep(struct thread *, void *, struct mtx *, int, char *, int);
int newnfs_request(struct nfsrv_descript *, struct nfsmount *,
struct nfsclient *, struct nfssockreq *, vnode_t, NFSPROC_T *,
struct ucred *, u_int32_t, u_int32_t, u_char *, int, u_int64_t *);
struct ucred *, u_int32_t, u_int32_t, u_char *, int, u_int64_t *,
struct nfsclsession *);
int newnfs_connect(struct nfsmount *, struct nfssockreq *,
struct ucred *, NFSPROC_T *, int);
void newnfs_disconnect(struct nfssockreq *);

View file

@ -49,7 +49,7 @@ struct nfsv4node {
*/
#define NFSCL_REQSTART(n, p, v) \
nfscl_reqstart((n), (p), VFSTONFS((v)->v_mount), \
VTONFS(v)->n_fhp->nfh_fh, VTONFS(v)->n_fhp->nfh_len, NULL)
VTONFS(v)->n_fhp->nfh_fh, VTONFS(v)->n_fhp->nfh_len, NULL, NULL)
/*
* These two macros convert between a lease duration and renew interval.

View file

@ -40,26 +40,75 @@ LIST_HEAD(nfsclhead, nfsclclient);
LIST_HEAD(nfsclownerhead, nfsclowner);
TAILQ_HEAD(nfscldeleghead, nfscldeleg);
LIST_HEAD(nfscldeleghash, nfscldeleg);
TAILQ_HEAD(nfscllayouthead, nfscllayout);
LIST_HEAD(nfscllayouthash, nfscllayout);
LIST_HEAD(nfsclflayouthead, nfsclflayout);
LIST_HEAD(nfscldevinfohead, nfscldevinfo);
LIST_HEAD(nfsclrecalllayouthead, nfsclrecalllayout);
#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]))
/* Structure for NFSv4.1 session stuff. */
struct nfsclsession {
struct mtx nfsess_mtx;
struct nfsslot nfsess_cbslots[NFSV4_CBSLOTS];
nfsquad_t nfsess_clientid;
uint32_t nfsess_slotseq[64]; /* Max for 64bit nm_slots */
uint64_t nfsess_slots;
uint32_t nfsess_sequenceid;
uint32_t nfsess_maxcache; /* Max size for cached reply. */
uint16_t nfsess_foreslots;
uint16_t nfsess_backslots;
uint8_t nfsess_sessionid[NFSX_V4SESSIONID];
};
/*
* This structure holds the session, clientid and related information
* needed for an NFSv4.1 Meta Data Server (MDS) or Data Server (DS).
* It is malloc'd to the correct length.
*/
struct nfsclds {
TAILQ_ENTRY(nfsclds) nfsclds_list;
struct nfsclsession nfsclds_sess;
struct mtx nfsclds_mtx;
struct nfssockreq *nfsclds_sockp;
time_t nfsclds_expire;
uint16_t nfsclds_flags;
uint16_t nfsclds_servownlen;
uint8_t nfsclds_verf[NFSX_VERF];
uint8_t nfsclds_serverown[0];
};
/*
* Flags for nfsclds_flags.
*/
#define NFSCLDS_HASWRITEVERF 0x0001
#define NFSCLDS_MDS 0x0002
#define NFSCLDS_DS 0x0004
struct nfsclclient {
LIST_ENTRY(nfsclclient) nfsc_list;
struct nfsclownerhead nfsc_owner;
struct nfscldeleghead nfsc_deleg;
struct nfscldeleghash nfsc_deleghash[NFSCLDELEGHASHSIZE];
struct nfsv4lock nfsc_lock;
struct proc *nfsc_renewthread;
struct nfsmount *nfsc_nmp;
nfsquad_t nfsc_clientid;
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_idlen;
u_int8_t nfsc_id[1]; /* Malloc'd to correct length */
struct nfscllayouthead nfsc_layout;
struct nfscllayouthash nfsc_layouthash[NFSCLLAYOUTHASHSIZE];
struct nfscldevinfohead nfsc_devinfo;
struct nfsv4lock nfsc_lock;
struct proc *nfsc_renewthread;
struct nfsmount *nfsc_nmp;
time_t nfsc_expire;
u_int32_t nfsc_clientidrev;
u_int32_t nfsc_rev;
u_int32_t nfsc_renew;
u_int32_t nfsc_cbident;
u_int16_t nfsc_flags;
u_int16_t nfsc_idlen;
u_int8_t nfsc_id[1]; /* Malloc'd to correct length */
};
/*
@ -175,6 +224,141 @@ struct nfscllockownerfh {
uint8_t nfslfh_fh[NFSX_V4FHMAX];
};
/*
* MALLOC'd to the correct length to accommodate the file handle.
*/
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;
struct nfsclflayouthead nfsly_flayrw;
struct nfsclrecalllayouthead nfsly_recall;
time_t nfsly_timestamp;
struct nfsclclient *nfsly_clp;
uint16_t nfsly_flags;
uint16_t nfsly_fhlen;
uint8_t nfsly_fh[1];
};
/*
* Flags for nfsly_flags.
*/
#define NFSLY_FILES 0x0001
#define NFSLY_BLOCK 0x0002
#define NFSLY_OBJECT 0x0004
#define NFSLY_RECALL 0x0008
#define NFSLY_RECALLFILE 0x0010
#define NFSLY_RECALLFSID 0x0020
#define NFSLY_RECALLALL 0x0040
#define NFSLY_RETONCLOSE 0x0080
#define NFSLY_WRITTEN 0x0100 /* Has been used to write to a DS. */
/*
* MALLOC'd to the correct length to accommodate the file handle list.
* These hang off of nfsly_flayread and nfsly_flayrw, sorted in increasing
* offset order.
* The nfsly_flayread list holds the ones with iomode == NFSLAYOUTIOMODE_READ,
* whereas the nfsly_flayrw holds the ones with iomode == NFSLAYOUTIOMODE_RW.
*/
struct nfsclflayout {
LIST_ENTRY(nfsclflayout) nfsfl_list;
uint8_t nfsfl_dev[NFSX_V4DEVICEID];
uint64_t nfsfl_off;
uint64_t nfsfl_end;
uint64_t nfsfl_patoff;
struct nfscldevinfo *nfsfl_devp;
uint32_t nfsfl_iomode;
uint32_t nfsfl_util;
uint32_t nfsfl_stripe1;
uint16_t nfsfl_flags;
uint16_t nfsfl_fhcnt;
struct nfsfh *nfsfl_fh[1]; /* FH list for DS */
};
/*
* Flags for nfsfl_flags.
*/
#define NFSFL_RECALL 0x0001 /* File layout has been recalled */
/*
* Structure that is used to store a LAYOUTRECALL.
*/
struct nfsclrecalllayout {
LIST_ENTRY(nfsclrecalllayout) nfsrecly_list;
uint64_t nfsrecly_off;
uint64_t nfsrecly_len;
int nfsrecly_recalltype;
uint32_t nfsrecly_iomode;
uint32_t nfsrecly_stateseqid;
};
/*
* Stores the NFSv4.1 Device Info. Malloc'd to the correct length to
* store the list of network connections and list of indices.
* nfsdi_data[] is allocated the following way:
* - nfsdi_addrcnt * struct nfsclds
* - stripe indices, each stored as one byte, since there can be many
* of them. (This implies a limit of 256 on nfsdi_addrcnt, since the
* indices select which address.)
*/
struct nfscldevinfo {
LIST_ENTRY(nfscldevinfo) nfsdi_list;
uint8_t nfsdi_deviceid[NFSX_V4DEVICEID];
struct nfsclclient *nfsdi_clp;
uint32_t nfsdi_refcnt;
uint32_t nfsdi_layoutrefs;
uint16_t nfsdi_stripecnt;
uint16_t nfsdi_addrcnt;
struct nfsclds *nfsdi_data[0];
};
/* These inline functions return values from nfsdi_data[]. */
/*
* Return a pointer to the address at "pos".
*/
static __inline struct nfsclds **
nfsfldi_addr(struct nfscldevinfo *ndi, int pos)
{
if (pos >= ndi->nfsdi_addrcnt)
return (NULL);
return (&ndi->nfsdi_data[pos]);
}
/*
* Return the Nth ("pos") stripe index.
*/
static __inline int
nfsfldi_stripeindex(struct nfscldevinfo *ndi, int pos)
{
uint8_t *valp;
if (pos >= ndi->nfsdi_stripecnt)
return (-1);
valp = (uint8_t *)&ndi->nfsdi_data[ndi->nfsdi_addrcnt];
valp += pos;
return ((int)*valp);
}
/*
* Set the Nth ("pos") stripe index to "val".
*/
static __inline void
nfsfldi_setstripeindex(struct nfscldevinfo *ndi, int pos, uint8_t val)
{
uint8_t *valp;
if (pos >= ndi->nfsdi_stripecnt)
return;
valp = (uint8_t *)&ndi->nfsdi_data[ndi->nfsdi_addrcnt];
valp += pos;
*valp = val;
}
/*
* Macro for incrementing the seqid#.
*/

View file

@ -228,6 +228,34 @@
*/
#define NFSV4OP_NOPS 40
/*
* Additional Ops for NFSv4.1.
*/
#define NFSV4OP_BACKCHANNELCTL 40
#define NFSV4OP_BINDCONNTOSESS 41
#define NFSV4OP_EXCHANGEID 42
#define NFSV4OP_CREATESESSION 43
#define NFSV4OP_DESTROYSESSION 44
#define NFSV4OP_FREESTATEID 45
#define NFSV4OP_GETDIRDELEG 46
#define NFSV4OP_GETDEVINFO 47
#define NFSV4OP_GETDEVLIST 48
#define NFSV4OP_LAYOUTCOMMIT 49
#define NFSV4OP_LAYOUTGET 50
#define NFSV4OP_LAYOUTRETURN 51
#define NFSV4OP_SECINFONONAME 52
#define NFSV4OP_SEQUENCE 53
#define NFSV4OP_SETSSV 54
#define NFSV4OP_TESTSTATEID 55
#define NFSV4OP_WANTDELEG 56
#define NFSV4OP_DESTROYCLIENTID 57
#define NFSV4OP_RECLAIMCOMPL 58
/*
* Must be one more than last op#.
*/
#define NFSV41_NOPS 59
/* Quirky case if the illegal op code */
#define NFSV4OP_OPILLEGAL 10044
@ -260,6 +288,20 @@
*/
#define NFSV4OP_CBNOPS 5
/*
* Additional Callback Ops for NFSv4.1 only. Not yet in nfsstats.
*/
#define NFSV4OP_CBLAYOUTRECALL 5
#define NFSV4OP_CBNOTIFY 6
#define NFSV4OP_CBPUSHDELEG 7
#define NFSV4OP_CBRECALLANY 8
#define NFSV4OP_CBRECALLOBJAVAIL 9
#define NFSV4OP_CBRECALLSLOT 10
#define NFSV4OP_CBSEQUENCE 11
#define NFSV4OP_CBWANTCANCELLED 12
#define NFSV4OP_CBNOTIFYLOCK 13
#define NFSV4OP_CBNOTIFYDEVID 14
/*
* The lower numbers -> 21 are used by NFSv2 and v3. These define higher
* numbers used by NFSv4.
@ -293,6 +335,27 @@
* Must be defined as one higher than the last Proc# above.
*/
#define NFSV4_NPROCS 41
/* Additional procedures for NFSv4.1. */
#define NFSPROC_EXCHANGEID 41
#define NFSPROC_CREATESESSION 42
#define NFSPROC_DESTROYSESSION 43
#define NFSPROC_DESTROYCLIENT 44
#define NFSPROC_FREESTATEID 45
#define NFSPROC_LAYOUTGET 46
#define NFSPROC_GETDEVICEINFO 47
#define NFSPROC_LAYOUTCOMMIT 48
#define NFSPROC_LAYOUTRETURN 49
#define NFSPROC_RECLAIMCOMPL 50
#define NFSPROC_WRITEDS 51
#define NFSPROC_READDS 52
#define NFSPROC_COMMITDS 53
/*
* Must be defined as one higher than the last NFSv4.1 Proc# above.
*/
#define NFSV41_NPROCS 54
#endif /* NFS_V3NPROCS */
/*
@ -368,13 +431,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>
@ -583,6 +646,8 @@ void nfsrvd_rcv(struct socket *, void *, int);
#define NFSPROCLISTUNLOCK() sx_sunlock(&allproc_lock)
#define NFSLOCKSOCKREQ(r) mtx_lock(&((r)->nr_mtx))
#define NFSUNLOCKSOCKREQ(r) mtx_unlock(&((r)->nr_mtx))
#define NFSLOCKDS(d) mtx_lock(&((d)->nfsclds_mtx))
#define NFSUNLOCKDS(d) mtx_unlock(&((d)->nfsclds_mtx))
/*
* Use these macros to initialize/free a mutex.
@ -672,6 +737,12 @@ 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);
MALLOC_DECLARE(M_NEWNFSSOCKREQ);
MALLOC_DECLARE(M_NEWNFSCLDS);
MALLOC_DECLARE(M_NEWNFSLAYRECALL);
#define M_NFSRVCACHE M_NEWNFSRVCACHE
#define M_NFSDCLIENT M_NEWNFSDCLIENT
#define M_NFSDSTATE M_NEWNFSDSTATE
@ -691,6 +762,12 @@ MALLOC_DECLARE(M_NEWNFSDROLLBACK);
#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
#define M_NFSSOCKREQ M_NEWNFSSOCKREQ
#define M_NFSCLDS M_NEWNFSCLDS
#define M_NFSLAYRECALL M_NEWNFSLAYRECALL
#define NFSINT_SIGMASK(set) \
(SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
@ -759,12 +836,16 @@ void newnfs_realign(struct mbuf **);
*/
#define NFSSTA_HASWRITEVERF 0x00040000 /* Has write verifier */
#define NFSSTA_GOTFSINFO 0x00100000 /* Got the fsinfo */
#define NFSSTA_NOLAYOUTCOMMIT 0x04000000 /* Don't do LayoutCommit */
#define NFSSTA_SESSPERSIST 0x08000000 /* Has a persistent session */
#define NFSSTA_TIMEO 0x10000000 /* Experiencing a timeout */
#define NFSSTA_LOCKTIMEO 0x20000000 /* Experiencing a lockd timeout */
#define NFSSTA_HASSETFSID 0x40000000 /* Has set the fsid */
#define NFSSTA_PNFS 0x80000000 /* pNFS is enabled */
#define NFSHASNFSV3(n) ((n)->nm_flag & NFSMNT_NFSV3)
#define NFSHASNFSV4(n) ((n)->nm_flag & NFSMNT_NFSV4)
#define NFSHASNFSV4N(n) ((n)->nm_minorvers > 0)
#define NFSHASNFSV3OR4(n) ((n)->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4))
#define NFSHASGOTFSINFO(n) ((n)->nm_state & NFSSTA_GOTFSINFO)
#define NFSHASHASSETFSID(n) ((n)->nm_state & NFSSTA_HASSETFSID)
@ -781,6 +862,10 @@ void newnfs_realign(struct mbuf **);
#define NFSHASPRIVACY(n) ((n)->nm_flag & NFSMNT_PRIVACY)
#define NFSSETWRITEVERF(n) ((n)->nm_state |= NFSSTA_HASWRITEVERF)
#define NFSSETHASSETFSID(n) ((n)->nm_state |= NFSSTA_HASSETFSID)
#define NFSHASPNFSOPT(n) ((n)->nm_flag & NFSMNT_PNFS)
#define NFSHASNOLAYOUTCOMMIT(n) ((n)->nm_state & NFSSTA_NOLAYOUTCOMMIT)
#define NFSHASSESSPERSIST(n) ((n)->nm_state & NFSSTA_SESSPERSIST)
#define NFSHASPNFS(n) ((n)->nm_state & NFSSTA_PNFS)
/*
* Gets the stats field out of the mount structure.

View file

@ -62,7 +62,9 @@
#define NFS_MINPACKET 20
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
#define NFSV4_MINORVERSION 0 /* V4 Minor version */
#define NFSV41_MINORVERSION 1 /* V4 Minor version */
#define NFSV4_CBVERS 1 /* V4 CB Version */
#define NFSV41_CBVERS 4 /* V4.1 CB Version */
#define NFSV4_SMALLSTR 50 /* Strings small enough for stack */
/* Stat numbers for rpc returns (version 2, 3 and 4) */
@ -145,6 +147,46 @@
#define NFSERR_ADMINREVOKED 10047
#define NFSERR_CBPATHDOWN 10048
/* NFSv4.1 specific errors. */
#define NFSERR_BADIOMODE 10049
#define NFSERR_BADLAYOUT 10050
#define NFSERR_BADSESSIONDIGEST 10051
#define NFSERR_BADSESSION 10052
#define NFSERR_BADSLOT 10053
#define NFSERR_COMPLETEALREADY 10054
#define NFSERR_NOTBNDTOSESS 10055
#define NFSERR_DELEGALREADYWANT 10056
#define NFSERR_BACKCHANBUSY 10057
#define NFSERR_LAYOUTTRYLATER 10058
#define NFSERR_LAYOUTUNAVAIL 10059
#define NFSERR_NOMATCHLAYOUT 10060
#define NFSERR_RECALLCONFLICT 10061
#define NFSERR_UNKNLAYOUTTYPE 10062
#define NFSERR_SEQMISORDERED 10063
#define NFSERR_SEQUENCEPOS 10064
#define NFSERR_REQTOOBIG 10065
#define NFSERR_REPTOOBIG 10066
#define NFSERR_REPTOOBIGTOCACHE 10067
#define NFSERR_RETRYUNCACHEDREP 10068
#define NFSERR_UNSAFECOMPOUND 10069
#define NFSERR_TOOMANYOPS 10070
#define NFSERR_OPNOTINSESS 10071
#define NFSERR_HASHALGUNSUPP 10072
#define NFSERR_CLIENTIDBUSY 10074
#define NFSERR_PNFSIOHOLE 10075
#define NFSERR_SEQFALSERETRY 10076
#define NFSERR_BADHIGHSLOT 10077
#define NFSERR_DEADSESSION 10078
#define NFSERR_ENCRALGUNSUPP 10079
#define NFSERR_PNFSNOLAYOUT 10080
#define NFSERR_NOTONLYOP 10081
#define NFSERR_WRONGCRED 10082
#define NFSERR_WRONGTYPE 10083
#define NFSERR_DIRDELEGUNAVAIL 10084
#define NFSERR_REJECTDELEG 10085
#define NFSERR_RETURNCONFLICT 10086
#define NFSERR_DELEGREVOKED 10087
#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
#define NFSERR_DONTREPLY 30003 /* Don't process request */
#define NFSERR_RETVOID 30004 /* Return void, not error */
@ -189,6 +231,8 @@
#define NFSX_V4SPECDATA (2 * NFSX_UNSIGNED)
#define NFSX_V4TIME (NFSX_HYPER + NFSX_UNSIGNED)
#define NFSX_V4SETTIME (NFSX_UNSIGNED + NFSX_V4TIME)
#define NFSX_V4SESSIONID 16
#define NFSX_V4DEVICEID 16
/* sizes common to multiple NFS versions */
#define NFSX_FHMAX (NFSX_V4FHMAX)
@ -258,6 +302,27 @@
* Must be defined as one higher than the last Proc# above.
*/
#define NFSV4_NPROCS 41
/* Additional procedures for NFSv4.1. */
#define NFSPROC_EXCHANGEID 41
#define NFSPROC_CREATESESSION 42
#define NFSPROC_DESTROYSESSION 43
#define NFSPROC_DESTROYCLIENT 44
#define NFSPROC_FREESTATEID 45
#define NFSPROC_LAYOUTGET 46
#define NFSPROC_GETDEVICEINFO 47
#define NFSPROC_LAYOUTCOMMIT 48
#define NFSPROC_LAYOUTRETURN 49
#define NFSPROC_RECLAIMCOMPL 50
#define NFSPROC_WRITEDS 51
#define NFSPROC_READDS 52
#define NFSPROC_COMMITDS 53
/*
* Must be defined as one higher than the last NFSv4.1 Proc# above.
*/
#define NFSV41_NPROCS 54
#endif /* NFS_V3NPROCS */
/*
@ -269,10 +334,10 @@
/*
* NFSPROC_NOOP is a fake op# that can't be the same as any V2/3/4 Procedure
* or Operation#. Since the NFS V4 Op #s go higher, use NFSV4OP_NOPS, which
* or Operation#. Since the NFS V4 Op #s go higher, use NFSV41_NOPS, which
* is one greater than the highest Op#.
*/
#define NFSPROC_NOOP NFSV4OP_NOPS
#define NFSPROC_NOOP NFSV41_NOPS
/* Actual Version 2 procedure numbers */
#define NFSV2PROC_NULL 0
@ -406,6 +471,7 @@
#define NFSSTATEID_PUTALLZERO 0
#define NFSSTATEID_PUTALLONE 1
#define NFSSTATEID_PUTSTATEID 2
#define NFSSTATEID_PUTSEQIDZERO 3
/*
* Bits for share access and deny.
@ -462,12 +528,70 @@
#define NFSCREATE_UNCHECKED 0
#define NFSCREATE_GUARDED 1
#define NFSCREATE_EXCLUSIVE 2
#define NFSCREATE_EXCLUSIVE41 3
#define NFSV3FSINFO_LINK 0x01
#define NFSV3FSINFO_SYMLINK 0x02
#define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10
/* Flags for Exchange ID */
#define NFSV4EXCH_SUPPMOVEDREFER 0x00000001
#define NFSV4EXCH_SUPPMOVEDMIGR 0x00000002
#define NFSV4EXCH_BINDPRINCSTATEID 0x00000100
#define NFSV4EXCH_USENONPNFS 0x00010000
#define NFSV4EXCH_USEPNFSMDS 0x00020000
#define NFSV4EXCH_USEPNFSDS 0x00040000
#define NFSV4EXCH_MASKPNFS 0x00070000
#define NFSV4EXCH_UPDCONFIRMEDRECA 0x40000000
#define NFSV4EXCH_CONFIRMEDR 0x80000000
/* State Protects */
#define NFSV4EXCH_SP4NONE 0
#define NFSV4EXCH_SP4MACHCRED 1
#define NFSV4EXCH_SP4SSV 2
/* Flags for Create Session */
#define NFSV4CRSESS_PERSIST 0x00000001
#define NFSV4CRSESS_CONNBACKCHAN 0x00000002
#define NFSV4CRSESS_CONNRDMA 0x00000004
/* Flags for Sequence */
#define NFSV4SEQ_CBPATHDOWN 0x00000001
#define NFSV4SEQ_CBGSSCONTEXPIRING 0x00000002
#define NFSV4SEQ_CBGSSCONTEXPIRED 0x00000004
#define NFSV4SEQ_EXPIREDALLSTATEREVOKED 0x00000008
#define NFSV4SEQ_EXPIREDSOMESTATEREVOKED 0x00000010
#define NFSV4SEQ_ADMINSTATEREVOKED 0x00000020
#define NFSV4SEQ_RECALLABLESTATEREVOKED 0x00000040
#define NFSV4SEQ_LEASEMOVED 0x00000080
#define NFSV4SEQ_RESTARTRECLAIMNEEDED 0x00000100
#define NFSV4SEQ_CBPATHDOWNSESSION 0x00000200
#define NFSV4SEQ_BACKCHANNELFAULT 0x00000400
#define NFSV4SEQ_DEVIDCHANGED 0x00000800
#define NFSV4SEQ_DEVIDDELETED 0x00001000
/* Flags for Layout. */
#define NFSLAYOUTRETURN_FILE 1
#define NFSLAYOUTRETURN_FSID 2
#define NFSLAYOUTRETURN_ALL 3
#define NFSLAYOUT_NFSV4_1_FILES 0x1
#define NFSLAYOUT_OSD2_OBJECTS 0x2
#define NFSLAYOUT_BLOCK_VOLUME 0x3
#define NFSLAYOUTIOMODE_READ 1
#define NFSLAYOUTIOMODE_RW 2
#define NFSLAYOUTIOMODE_ANY 3
/* Flags for Get Device Info. */
#define NFSDEVICEIDNOTIFY_CHANGEBIT 0x1
#define NFSDEVICEIDNOTIFY_DELETEBIT 0x2
/* Flags for File Layout. */
#define NFSFLAYUTIL_DENSE 0x1
#define NFSFLAYUTIL_COMMIT_THRU_MDS 0x2
/* Conversion macros */
#define vtonfsv2_mode(t,m) \
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \

View file

@ -1371,6 +1371,8 @@ ncl_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg)
goto out;
error = vinvalbuf(vp, flags, 0, slptimeo);
}
if (NFSHASPNFS(nmp))
nfscl_layoutcommit(vp, td);
mtx_lock(&np->n_mtx);
if (np->n_directio_asyncwr == 0)
np->n_flag &= ~NMODIFIED;

View file

@ -43,10 +43,11 @@ __FBSDID("$FreeBSD$");
#include <fs/nfs/nfsport.h>
extern struct nfsstats newnfsstats;
extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS];
extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
extern int ncl_mbuf_mlen;
extern enum vtype newnv2tov_type[8];
extern enum vtype nv34tov_type[8];
extern int nfs_bigreply[NFSV41_NPROCS];
NFSCLSTATEMUTEX;
#endif /* !APPLEKEXT */
@ -56,7 +57,7 @@ static struct {
int opcnt;
const u_char *tag;
int taglen;
} nfsv4_opmap[NFS_NPROCS] = {
} nfsv4_opmap[NFSV41_NPROCS] = {
{ 0, 1, "Null", 4 },
{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
{ NFSV4OP_SETATTR, 2, "Setattr", 7, },
@ -98,15 +99,28 @@ static struct {
{ NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, },
{ NFSV4OP_GETATTR, 1, "Getacl", 6, },
{ NFSV4OP_SETATTR, 1, "Setacl", 6, },
{ NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, },
{ NFSV4OP_CREATESESSION, 1, "CreateSession", 13, },
{ NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, },
{ NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, },
{ NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, },
{ NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, },
{ NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, },
{ NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, },
{ NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, },
{ NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
{ NFSV4OP_WRITE, 1, "WriteDS", 7, },
{ NFSV4OP_READ, 1, "ReadDS", 6, },
{ NFSV4OP_COMMIT, 1, "CommitDS", 8, },
};
/*
* NFS RPCS that have large request message size.
*/
static int nfs_bigrequest[NFS_NPROCS] = {
static int nfs_bigrequest[NFSV41_NPROCS] = {
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0
};
/*
@ -115,7 +129,7 @@ static int nfs_bigrequest[NFS_NPROCS] = {
*/
APPLESTATIC void
nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp)
u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep)
{
struct mbuf *mb;
u_int32_t *tl;
@ -125,9 +139,12 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
/*
* First, fill in some of the fields of nd.
*/
if (NFSHASNFSV4(nmp))
nd->nd_slotseq = NULL;
if (NFSHASNFSV4(nmp)) {
nd->nd_flag = ND_NFSV4 | ND_NFSCL;
else if (NFSHASNFSV3(nmp))
if (NFSHASNFSV4N(nmp))
nd->nd_flag |= ND_NFSV41;
} else if (NFSHASNFSV3(nmp))
nd->nd_flag = ND_NFSV3 | ND_NFSCL;
else
nd->nd_flag = ND_NFSV2 | ND_NFSCL;
@ -151,33 +168,71 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
if (nd->nd_flag & ND_NFSV4) {
opcnt = nfsv4_opmap[procnum].opcnt +
nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
if ((nd->nd_flag & ND_NFSV41) != 0) {
opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
if (procnum == NFSPROC_RENEW)
/*
* For the special case of Renew, just do a
* Sequence Op.
*/
opcnt = 1;
else if (procnum == NFSPROC_WRITEDS ||
procnum == NFSPROC_COMMITDS)
/*
* For the special case of a Writeor Commit to
* a DS, the opcnt == 3, for Sequence, PutFH,
* Write/Commit.
*/
opcnt = 3;
}
/*
* What should the tag really be?
*/
(void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
nfsv4_opmap[procnum].taglen);
NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(NFSV4_MINORVERSION);
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
if ((nd->nd_flag & ND_NFSV41) != 0)
*tl++ = txdr_unsigned(NFSV41_MINORVERSION);
else
*tl++ = txdr_unsigned(NFSV4_MINORVERSION);
if (opcntpp != NULL)
*opcntpp = tl;
*tl++ = txdr_unsigned(opcnt);
*tl = txdr_unsigned(opcnt);
if ((nd->nd_flag & ND_NFSV41) != 0 &&
nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(NFSV4OP_SEQUENCE);
if (sep == NULL)
nfsv4_setsequence(nd, NFSMNT_MDSSESSION(nmp),
nfs_bigreply[procnum]);
else
nfsv4_setsequence(nd, sep,
nfs_bigreply[procnum]);
}
if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(NFSV4OP_PUTFH);
(void) nfsm_fhtom(nd, nfhp, fhlen, 0);
if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh==2){
if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
== 2 && procnum != NFSPROC_WRITEDS &&
procnum != NFSPROC_COMMITDS) {
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(NFSV4OP_GETATTR);
NFSWCCATTR_ATTRBIT(&attrbits);
(void) nfsrv_putattrbit(nd, &attrbits);
nd->nd_flag |= ND_V4WCCATTR;
}
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
}
*tl = txdr_unsigned(nfsv4_opmap[procnum].op);
if (procnum != NFSPROC_RENEW ||
(nd->nd_flag & ND_NFSV41) == 0) {
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(nfsv4_opmap[procnum].op);
}
} else {
(void) nfsm_fhtom(nd, nfhp, fhlen, 0);
}
NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]);
if (procnum < NFSV4_NPROCS)
NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]);
}
#ifndef APPLE
@ -453,6 +508,11 @@ nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
st->other[0] = 0xffffffff;
st->other[1] = 0xffffffff;
st->other[2] = 0xffffffff;
} else if (flag == NFSSTATEID_PUTSEQIDZERO) {
st->seqid = 0;
st->other[0] = stateidp->other[0];
st->other[1] = stateidp->other[1];
st->other[2] = stateidp->other[2];
} else {
st->seqid = stateidp->seqid;
st->other[0] = stateidp->other[0];

View file

@ -92,7 +92,7 @@ struct dtnfsclient_rpc {
* This table is indexed by NFSv3 procedure number, but also used for NFSv2
* procedure names and NFSv4 operations.
*/
static struct dtnfsclient_rpc dtnfsclient_rpcs[NFS_NPROCS + 1] = {
static struct dtnfsclient_rpc dtnfsclient_rpcs[NFSV41_NPROCS + 1] = {
{ "null", "null", "null" },
{ "getattr", "getattr", "getattr" },
{ "setattr", "setattr", "setattr" },
@ -196,17 +196,17 @@ extern uint32_t nfscl_attrcache_load_done_id;
* stored in one of these two NFS client-allocated arrays; 0 indicates that
* the event is not being traced so probes should not be called.
*
* For simplicity, we allocate both v2, v3 and v4 arrays as NFS_NPROCS + 1, and
* the v2, v3 arrays are simply sparse.
* For simplicity, we allocate both v2, v3 and v4 arrays as NFSV41_NPROCS + 1,
* and the v2, v3 arrays are simply sparse.
*/
extern uint32_t nfscl_nfs2_start_probes[NFS_NPROCS + 1];
extern uint32_t nfscl_nfs2_done_probes[NFS_NPROCS + 1];
extern uint32_t nfscl_nfs2_start_probes[NFSV41_NPROCS + 1];
extern uint32_t nfscl_nfs2_done_probes[NFSV41_NPROCS + 1];
extern uint32_t nfscl_nfs3_start_probes[NFS_NPROCS + 1];
extern uint32_t nfscl_nfs3_done_probes[NFS_NPROCS + 1];
extern uint32_t nfscl_nfs3_start_probes[NFSV41_NPROCS + 1];
extern uint32_t nfscl_nfs3_done_probes[NFSV41_NPROCS + 1];
extern uint32_t nfscl_nfs4_start_probes[NFS_NPROCS + 1];
extern uint32_t nfscl_nfs4_done_probes[NFS_NPROCS + 1];
extern uint32_t nfscl_nfs4_start_probes[NFSV41_NPROCS + 1];
extern uint32_t nfscl_nfs4_done_probes[NFSV41_NPROCS + 1];
/*
* Look up a DTrace probe ID to see if it's associated with a "done" event --
@ -217,7 +217,7 @@ dtnfs234_isdoneprobe(dtrace_id_t id)
{
int i;
for (i = 0; i < NFS_NPROCS + 1; i++) {
for (i = 0; i < NFSV41_NPROCS + 1; i++) {
if (dtnfsclient_rpcs[i].nr_v4_id_done == id ||
dtnfsclient_rpcs[i].nr_v3_id_done == id ||
dtnfsclient_rpcs[i].nr_v2_id_done == id)
@ -401,7 +401,7 @@ dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
* Register NFSv2 RPC procedures; note sparseness check for each slot
* in the NFSv3, NFSv4 procnum-indexed array.
*/
for (i = 0; i < NFS_NPROCS + 1; i++) {
for (i = 0; i < NFSV41_NPROCS + 1; i++) {
if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) ==
@ -430,7 +430,7 @@ dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
* Register NFSv3 RPC procedures; note sparseness check for each slot
* in the NFSv4 procnum-indexed array.
*/
for (i = 0; i < NFS_NPROCS + 1; i++) {
for (i = 0; i < NFSV41_NPROCS + 1; i++) {
if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) ==
@ -458,7 +458,7 @@ dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
/*
* Register NFSv4 RPC procedures.
*/
for (i = 0; i < NFS_NPROCS + 1; i++) {
for (i = 0; i < NFSV41_NPROCS + 1; i++) {
if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_start_str) ==
0) {

View file

@ -45,12 +45,13 @@ __FBSDID("$FreeBSD$");
NFSDLOCKMUTEX;
SVCPOOL *nfscbd_pool;
extern SVCPOOL *nfscbd_pool;
static int nfs_cbproc(struct nfsrv_descript *, u_int32_t);
extern u_long sb_max_adj;
extern int nfs_numnfscbd;
extern int nfscl_debuglevel;
/*
* NFS client system calls for handling callbacks.
@ -90,6 +91,7 @@ nfscb_program(struct svc_req *rqst, SVCXPRT *xprt)
nd.nd_mreq = NULL;
nd.nd_cred = NULL;
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);
@ -133,9 +135,10 @@ nfscb_program(struct svc_req *rqst, SVCXPRT *xprt)
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
NFSCL_DEBUG(1, "cbrep sent\n");
svc_freereq(rqst);
}
@ -271,13 +274,15 @@ nfsrvd_cbinit(int terminating)
NFSD_LOCK_ASSERT();
if (terminating) {
/* Wait for any xprt registrations to complete. */
while (nfs_numnfscbd > 0)
msleep(&nfs_numnfscbd, NFSDLOCKMUTEXPTR, PZERO,
"nfscbdt", 0);
NFSD_UNLOCK();
svcpool_destroy(nfscbd_pool);
nfscbd_pool = NULL;
NFSD_LOCK();
}
NFSD_UNLOCK();
} else
NFSD_UNLOCK();
nfscbd_pool = svcpool_create("nfscbd", NULL);
nfscbd_pool->sp_rcache = NULL;

View file

@ -853,7 +853,7 @@ nfscl_request(struct nfsrv_descript *nd, struct vnode *vp, NFSPROC_T *p,
else
vers = NFS_VER2;
ret = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred,
NFS_PROG, vers, NULL, 1, NULL);
NFS_PROG, vers, NULL, 1, NULL, NULL);
return (ret);
}
@ -1112,10 +1112,15 @@ nfscl_maperr(struct thread *td, int error, uid_t uid, gid_t gid)
"No name and/or group mapping for uid,gid:(%d,%d)\n",
uid, gid);
return (EPERM);
case NFSERR_BADNAME:
case NFSERR_BADCHAR:
printf("nfsv4 char/name not handled by server\n");
return (ENOENT);
case NFSERR_STALECLIENTID:
case NFSERR_STALESTATEID:
case NFSERR_EXPIRED:
case NFSERR_BADSTATEID:
case NFSERR_BADSESSION:
printf("nfsv4 recover err returned %d\n", error);
return (EIO);
case NFSERR_BADHANDLE:
@ -1131,8 +1136,6 @@ nfscl_maperr(struct thread *td, int error, uid_t uid, gid_t gid)
case NFSERR_LEASEMOVED:
case NFSERR_RECLAIMBAD:
case NFSERR_BADXDR:
case NFSERR_BADCHAR:
case NFSERR_BADNAME:
case NFSERR_OPILLEGAL:
printf("nfsv4 client/server protocol prob err=%d\n",
error);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -80,6 +80,8 @@ extern int nfscl_ticks;
extern struct timeval nfsboottime;
extern struct nfsstats newnfsstats;
extern int nfsrv_useacl;
extern int nfscl_debuglevel;
NFSCLSTATEMUTEX;
MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
@ -104,7 +106,7 @@ static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
static int mountnfs(struct nfs_args *, struct mount *,
struct sockaddr *, char *, u_char *, int, u_char *, int,
u_char *, int, struct vnode **, struct ucred *,
struct thread *, int, int);
struct thread *, int, int, int);
static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
struct sockaddr_storage *, int *, off_t *,
struct timeval *);
@ -296,9 +298,11 @@ nfs_statfs(struct mount *mp, struct statfs *sbp)
if (!error)
error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
&attrflag, NULL);
if (error != 0)
NFSCL_DEBUG(2, "statfs=%d\n", error);
if (attrflag == 0) {
ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
td->td_ucred, td, &nfsva, NULL);
td->td_ucred, td, &nfsva, NULL, NULL);
if (ret) {
/*
* Just set default values to get things going.
@ -521,7 +525,7 @@ nfs_mountdiskless(char *path,
nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
printf("nfs_mountroot: mount %s on /: %d\n", path, error);
return (error);
}
@ -715,8 +719,8 @@ static const char *nfs_opts[] = { "from", "nfs_args",
"readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
"retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
"readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
"principal", "nfsv4", "gssname", "allgssname", "dirpath",
"nametimeo", "negnametimeo", "nocto", "wcommitsize",
"principal", "nfsv4", "gssname", "allgssname", "dirpath", "minorversion",
"nametimeo", "negnametimeo", "nocto", "pnfs", "wcommitsize",
NULL };
/*
@ -763,6 +767,7 @@ nfs_mount(struct mount *mp)
char *opt, *name, *secname;
int nametimeo = NFS_DEFAULT_NAMETIMEO;
int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
int minvers = 0;
int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
size_t hstlen;
@ -836,6 +841,8 @@ nfs_mount(struct mount *mp)
args.flags |= NFSMNT_ALLGSSNAME;
if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
args.flags |= NFSMNT_NOCTO;
if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
args.flags |= NFSMNT_PNFS;
if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
if (opt == NULL) {
vfs_mount_error(mp, "illegal readdirsize");
@ -988,6 +995,16 @@ nfs_mount(struct mount *mp)
goto out;
}
}
if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
0) {
ret = sscanf(opt, "%d", &minvers);
if (ret != 1 || minvers < 0 || minvers > 1 ||
(args.flags & NFSMNT_NFSV4) == 0) {
vfs_mount_error(mp, "illegal minorversion: %s", opt);
error = EINVAL;
goto out;
}
}
if (vfs_getopt(mp->mnt_optnew, "sec",
(void **) &secname, NULL) == 0)
nfs_sec_name(secname, &args.flags);
@ -1132,7 +1149,7 @@ nfs_mount(struct mount *mp)
args.fh = nfh;
error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
nametimeo, negnametimeo);
nametimeo, negnametimeo, minvers);
out:
if (!error) {
MNT_ILOCK(mp);
@ -1176,14 +1193,20 @@ static int
mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo)
struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
int minvers)
{
struct nfsmount *nmp;
struct nfsnode *np;
int error, trycnt, ret;
struct nfsvattr nfsva;
struct nfsclclient *clp;
struct nfsclds *dsp, *tdsp;
uint32_t lease;
static u_int64_t clval = 0;
NFSCL_DEBUG(3, "in mnt\n");
clp = NULL;
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
@ -1259,6 +1282,10 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
else
nmp->nm_wcommitsize = hibufspace / 10;
if ((argp->flags & NFSMNT_NFSV4) != 0)
nmp->nm_minorvers = minvers;
else
nmp->nm_minorvers = 0;
nfs_decode_args(mp, nmp, argp, hst, cred, td);
@ -1306,6 +1333,35 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
goto bad;
/* For NFSv4.1, get the clientid now. */
if (nmp->nm_minorvers > 0) {
NFSCL_DEBUG(3, "at getcl\n");
error = nfscl_getcl(mp, cred, td, 0, &clp);
NFSCL_DEBUG(3, "aft getcl=%d\n", error);
if (error != 0)
goto bad;
}
if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
nmp->nm_dirpathlen > 0) {
NFSCL_DEBUG(3, "in dirp\n");
/*
* If the fhsize on the mount point == 0 for V4, the mount
* path needs to be looked up.
*/
trycnt = 3;
do {
error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
cred, td);
NFSCL_DEBUG(3, "aft dirp=%d\n", error);
if (error)
(void) nfs_catnap(PZERO, error, "nfsgetdirp");
} while (error && --trycnt > 0);
if (error) {
error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
goto bad;
}
}
/*
* A reference count is needed on the nfsnode representing the
@ -1315,24 +1371,6 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
* this problem, because one can identify root inodes by their
* number == ROOTINO (2).
*/
if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
nmp->nm_dirpathlen > 0) {
/*
* If the fhsize on the mount point == 0 for V4, the mount
* path needs to be looked up.
*/
trycnt = 3;
do {
error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
cred, td);
if (error)
(void) nfs_catnap(PZERO, error, "nfsgetdirp");
} while (error && --trycnt > 0);
if (error) {
error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
goto bad;
}
}
if (nmp->nm_fhsize > 0) {
/*
* Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
@ -1352,7 +1390,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
* (*vpp)->v_type with the correct value.
*/
ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
cred, td, &nfsva, NULL);
cred, td, &nfsva, NULL, &lease);
if (ret) {
/*
* Just set default values to get things going.
@ -1367,8 +1405,25 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
nfsva.na_vattr.va_gen = 1;
nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
nfsva.na_vattr.va_size = 512 * 1024;
lease = 60;
}
(void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
if (nmp->nm_minorvers > 0) {
NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
NFSLOCKCLSTATE();
clp->nfsc_renew = NFSCL_RENEW(lease);
clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
clp->nfsc_clientidrev++;
if (clp->nfsc_clientidrev == 0)
clp->nfsc_clientidrev++;
NFSUNLOCKCLSTATE();
/*
* Mount will succeed, so the renew thread can be
* started now.
*/
nfscl_start_renewthread(clp);
nfscl_clientrelease(clp);
}
if (argp->flags & NFSMNT_NFSV3)
ncl_fsinfo(nmp, *vpp, cred, td);
@ -1390,10 +1445,20 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
error = EIO;
bad:
if (clp != NULL)
nfscl_clientrelease(clp);
newnfs_disconnect(&nmp->nm_sockreq);
crfree(nmp->nm_sockreq.nr_cred);
mtx_destroy(&nmp->nm_sockreq.nr_mtx);
mtx_destroy(&nmp->nm_mtx);
if (nmp->nm_clp != NULL) {
NFSLOCKCLSTATE();
LIST_REMOVE(nmp->nm_clp, nfsc_list);
NFSUNLOCKCLSTATE();
free(nmp->nm_clp, M_NFSCLCLIENT);
}
TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
nfscl_freenfsclds(dsp);
FREE(nmp, M_NEWNFSMNT);
FREE(nam, M_SONAME);
return (error);
@ -1408,6 +1473,7 @@ nfs_unmount(struct mount *mp, int mntflags)
struct thread *td;
struct nfsmount *nmp;
int error, flags = 0, trycnt = 0;
struct nfsclds *dsp, *tdsp;
td = curthread;
@ -1448,6 +1514,8 @@ nfs_unmount(struct mount *mp, int mntflags)
mtx_destroy(&nmp->nm_sockreq.nr_mtx);
mtx_destroy(&nmp->nm_mtx);
TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
nfscl_freenfsclds(dsp);
FREE(nmp, M_NEWNFSMNT);
out:
return (error);

View file

@ -103,6 +103,7 @@ uint32_t nfscl_accesscache_load_done_id;
extern struct nfsstats newnfsstats;
extern int nfsrv_useacl;
extern int nfscl_debuglevel;
MALLOC_DECLARE(M_NEWNFSREQ);
/*
@ -606,6 +607,10 @@ nfs_open(struct vop_open_args *ap)
np->n_directio_opens++;
}
/* If opened for writing via NFSv4.1 or later, mark that for pNFS. */
if (NFSHASPNFS(VFSTONFS(vp->v_mount)) && (fmode & FWRITE) != 0)
np->n_flag |= NWRITEOPENED;
/*
* If this is an open for writing, capture a reference to the
* credentials, so they can be used by ncl_putpages(). Using
@ -619,6 +624,7 @@ nfs_open(struct vop_open_args *ap)
} else
cred = NULL;
mtx_unlock(&np->n_mtx);
if (cred != NULL)
crfree(cred);
vnode_create_vobject(vp, vattr.va_size, ap->a_td);
@ -1362,9 +1368,18 @@ ncl_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
{
int error, ret, attrflag;
struct nfsvattr nfsva;
struct nfsmount *nmp;
error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva, &attrflag,
NULL);
nmp = VFSTONFS(vnode_mount(vp));
error = EIO;
attrflag = 0;
if (NFSHASPNFS(nmp))
error = nfscl_doiods(vp, uiop, NULL, NULL,
NFSV4OPEN_ACCESSREAD, cred, uiop->uio_td);
NFSCL_DEBUG(4, "readrpc: aft doiods=%d\n", error);
if (error != 0)
error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva,
&attrflag, NULL);
if (attrflag) {
ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
if (ret && !error)
@ -1383,10 +1398,20 @@ ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
int *iomode, int *must_commit, int called_from_strategy)
{
struct nfsvattr nfsva;
int error = 0, attrflag, ret;
int error, attrflag, ret;
struct nfsmount *nmp;
error = nfsrpc_write(vp, uiop, iomode, must_commit, cred,
uiop->uio_td, &nfsva, &attrflag, NULL, called_from_strategy);
nmp = VFSTONFS(vnode_mount(vp));
error = EIO;
attrflag = 0;
if (NFSHASPNFS(nmp))
error = nfscl_doiods(vp, uiop, iomode, must_commit,
NFSV4OPEN_ACCESSWRITE, cred, uiop->uio_td);
NFSCL_DEBUG(4, "writerpc: aft doiods=%d\n", error);
if (error != 0)
error = nfsrpc_write(vp, uiop, iomode, must_commit, cred,
uiop->uio_td, &nfsva, &attrflag, NULL,
called_from_strategy);
if (attrflag) {
if (VTONFS(vp)->n_flag & ND_NFSV4)
ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 1,
@ -2534,7 +2559,6 @@ ncl_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
struct nfsvattr nfsva;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
int error, attrflag;
u_char verf[NFSX_VERF];
mtx_lock(&nmp->nm_mtx);
if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) {
@ -2542,21 +2566,13 @@ ncl_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
return (0);
}
mtx_unlock(&nmp->nm_mtx);
error = nfsrpc_commit(vp, offset, cnt, cred, td, verf, &nfsva,
error = nfsrpc_commit(vp, offset, cnt, cred, td, &nfsva,
&attrflag, NULL);
if (!error) {
mtx_lock(&nmp->nm_mtx);
if (NFSBCMP((caddr_t)nmp->nm_verf, verf, NFSX_VERF)) {
NFSBCOPY(verf, (caddr_t)nmp->nm_verf, NFSX_VERF);
error = NFSERR_STALEWRITEVERF;
}
mtx_unlock(&nmp->nm_mtx);
if (!error && attrflag)
(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL,
0, 1);
} else if (NFS_ISV4(vp)) {
if (attrflag != 0)
(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL,
0, 1);
if (error != 0 && NFS_ISV4(vp))
error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
}
return (error);
}
@ -2928,6 +2944,8 @@ ncl_flush(struct vnode *vp, int waitfor, struct ucred *cred, struct thread *td,
mtx_unlock(&np->n_mtx);
} else
BO_UNLOCK(bo);
if (NFSHASPNFS(nmp))
nfscl_layoutcommit(vp, td);
mtx_lock(&np->n_mtx);
if (np->n_flag & NWRITEERR) {
error = np->n_error;

View file

@ -70,10 +70,12 @@ struct nfsmount {
int nm_negnametimeo; /* timeout for -ve entries (sec) */
/* Newnfs additions */
TAILQ_HEAD(, nfsclds) nm_sess; /* Session(s) for NFSv4.1. */
struct nfsclclient *nm_clp;
uid_t nm_uid; /* Uid for SetClientID etc. */
u_int64_t nm_clval; /* identifies which clientid */
u_int64_t nm_fsid[2]; /* NFSv4 fsid */
int nm_minorvers; /* Minor version # for NFSv4 */
u_int16_t nm_krbnamelen; /* Krb5 host principal, if any */
u_int16_t nm_dirpathlen; /* and mount dirpath, for V4 */
u_int16_t nm_srvkrbnamelen; /* and the server's target name */
@ -107,6 +109,12 @@ struct nfsmount {
*/
#define VFSTONFS(mp) ((struct nfsmount *)((mp)->mnt_data))
/*
* Get a pointer to the MDS session, which is always the first element
* in the list.
*/
#define NFSMNT_MDSSESSION(m) (&(TAILQ_FIRST(&((m)->nm_sess))->nfsclds_sess))
#ifndef NFS_DEFAULT_NAMETIMEO
#define NFS_DEFAULT_NAMETIMEO 60
#endif

View file

@ -155,6 +155,8 @@ struct nfsnode {
#define NREMOVEWANT 0x00004000 /* Want notification that remove is done */
#define NLOCK 0x00008000 /* Sleep lock the node */
#define NLOCKWANT 0x00010000 /* Want the sleep lock */
#define NNOLAYOUT 0x00020000 /* Can't get a layout for this file */
#define NWRITEOPENED 0x00040000 /* Has been opened for writing */
/*
* Convert between nfsnode pointers and vnode pointers

View file

@ -3780,7 +3780,8 @@ nfsrv_docallback(struct nfsclient *clp, int procnum,
newnfs_sndunlock(&clp->lc_req.nr_lock);
if (!error) {
error = newnfs_request(nd, NULL, clp, &clp->lc_req, NULL,
NULL, cred, clp->lc_program, NFSV4_CBVERS, NULL, 1, NULL);
NULL, cred, clp->lc_program, NFSV4_CBVERS, NULL, 1, NULL,
NULL);
}
NFSFREECRED(cred);

View file

@ -98,5 +98,6 @@ struct nfs_args {
#define NFSMNT_ALLGSSNAME 0x08000000 /* Use principal for all accesses */
#define NFSMNT_STRICT3530 0x10000000 /* Adhere strictly to RFC3530 */
#define NFSMNT_NOCTO 0x20000000 /* Don't flush attrcache on open */
#define NFSMNT_PNFS 0x40000000 /* Enable pNFS support */
#endif