summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient/nfs_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfsclient/nfs_socket.c')
-rw-r--r--sys/nfsclient/nfs_socket.c1157
1 files changed, 115 insertions, 1042 deletions
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index 8991672..4bf50e4 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -34,9 +34,11 @@
* SUCH DAMAGE.
*
* @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* Socket operations for use by nfs
*/
@@ -63,13 +65,11 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
+#include <nfsclient/nfs.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsrtt.h>
-#include <nfs/nqnfs.h>
+#include <nfsclient/nfsm_subs.h>
+#include <nfsclient/nfsmount.h>
+#include <nfsclient/nfsnode.h>
#define TRUE 1
#define FALSE 0
@@ -93,17 +93,6 @@
((((n)->nm_srtt[t-1] + 7) >> 3) + (n)->nm_sdrtt[t-1] + 1)))
#define NFS_SRTT(r) (r)->r_nmp->nm_srtt[proct[(r)->r_procnum] - 1]
#define NFS_SDRTT(r) (r)->r_nmp->nm_sdrtt[proct[(r)->r_procnum] - 1]
-/*
- * External data, mostly RPC constants in XDR form
- */
-extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers,
- rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr,
- rpc_auth_kerb;
-extern u_int32_t nfs_prog, nqnfs_prog;
-extern time_t nqnfsstarttime;
-extern struct nfsstats nfsstats;
-extern int nfsv3_procid[NFS_NPROCS];
-extern int nfs_ticks;
/*
* Defines which timer to use for the procnum.
@@ -115,12 +104,11 @@ extern int nfs_ticks;
*/
static int proct[NFS_NPROCS] = {
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
- 0, 0, 0,
};
-static int nfs_realign_test;
-static int nfs_realign_count;
-static int nfs_bufpackets = 4;
+static int nfs_realign_test;
+static int nfs_realign_count;
+static int nfs_bufpackets = 4;
SYSCTL_DECL(_vfs_nfs);
@@ -145,64 +133,26 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, "");
#define NFS_CWNDSCALE 256
#define NFS_MAXCWND (NFS_CWNDSCALE * 32)
static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
-int nfsrtton = 0;
-struct nfsrtt nfsrtt;
struct callout_handle nfs_timer_handle;
-static int nfs_msg __P((struct thread *,char *,char *));
-static int nfs_rcvlock __P((struct nfsreq *));
-static void nfs_rcvunlock __P((struct nfsreq *));
-static void nfs_realign __P((struct mbuf **pm, int hsiz));
-static int nfs_receive __P((struct nfsreq *rep, struct sockaddr **aname,
- struct mbuf **mp));
-static void nfs_softterm __P((struct nfsreq *rep));
-static int nfs_reconnect __P((struct nfsreq *rep));
-#ifndef NFS_NOSERVER
-static int nfsrv_getstream __P((struct nfssvc_sock *,int));
-
-int (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct thread *td,
- struct mbuf **mreqp)) = {
- nfsrv_null,
- nfsrv_getattr,
- nfsrv_setattr,
- nfsrv_lookup,
- nfsrv3_access,
- nfsrv_readlink,
- nfsrv_read,
- nfsrv_write,
- nfsrv_create,
- nfsrv_mkdir,
- nfsrv_symlink,
- nfsrv_mknod,
- nfsrv_remove,
- nfsrv_rmdir,
- nfsrv_rename,
- nfsrv_link,
- nfsrv_readdir,
- nfsrv_readdirplus,
- nfsrv_statfs,
- nfsrv_fsinfo,
- nfsrv_pathconf,
- nfsrv_commit,
- nqnfsrv_getlease,
- nqnfsrv_vacated,
- nfsrv_noop,
- nfsrv_noop
-};
-#endif /* NFS_NOSERVER */
+static int nfs_msg(struct thread *, char *, char *);
+static int nfs_rcvlock(struct nfsreq *);
+static void nfs_rcvunlock(struct nfsreq *);
+static void nfs_realign(struct mbuf **pm, int hsiz);
+static int nfs_receive(struct nfsreq *rep, struct sockaddr **aname,
+ struct mbuf **mp);
+static int nfs_reply(struct nfsreq *);
+static void nfs_softterm(struct nfsreq *rep);
+static int nfs_reconnect(struct nfsreq *rep);
/*
* Initialize sockets and congestion for a new NFS connection.
* We do not free the sockaddr if error.
*/
int
-nfs_connect(nmp, rep)
- register struct nfsmount *nmp;
- struct nfsreq *rep;
+nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
{
- register struct socket *so;
+ struct socket *so;
int s, error, rcvreserve, sndreserve;
int pktscale;
struct sockaddr *saddr;
@@ -364,7 +314,7 @@ nfs_connect(nmp, rep)
so->so_snd.sb_flags |= SB_NOINTR;
/* Initialize other non-zero congestion variables */
- nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] =
+ nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] =
nmp->nm_srtt[3] = (NFS_TIMEO << 3);
nmp->nm_sdrtt[0] = nmp->nm_sdrtt[1] = nmp->nm_sdrtt[2] =
nmp->nm_sdrtt[3] = 0;
@@ -388,11 +338,10 @@ bad:
* nb: Must be called with the nfs_sndlock() set on the mount point.
*/
static int
-nfs_reconnect(rep)
- register struct nfsreq *rep;
+nfs_reconnect(struct nfsreq *rep)
{
- register struct nfsreq *rp;
- register struct nfsmount *nmp = rep->r_nmp;
+ struct nfsreq *rp;
+ struct nfsmount *nmp = rep->r_nmp;
int error;
nfs_disconnect(nmp);
@@ -406,7 +355,7 @@ nfs_reconnect(rep)
* Loop through outstanding request list and fix up all requests
* on old socket.
*/
- for (rp = nfs_reqq.tqh_first; rp != 0; rp = rp->r_chain.tqe_next) {
+ TAILQ_FOREACH(rp, &nfs_reqq, r_chain) {
if (rp->r_nmp == nmp)
rp->r_flags |= R_MUSTRESEND;
}
@@ -417,10 +366,9 @@ nfs_reconnect(rep)
* NFS disconnect. Clean up and unlink.
*/
void
-nfs_disconnect(nmp)
- register struct nfsmount *nmp;
+nfs_disconnect(struct nfsmount *nmp)
{
- register struct socket *so;
+ struct socket *so;
if (nmp->nm_so) {
so = nmp->nm_so;
@@ -431,8 +379,7 @@ nfs_disconnect(nmp)
}
void
-nfs_safedisconnect(nmp)
- struct nfsmount *nmp;
+nfs_safedisconnect(struct nfsmount *nmp)
{
struct nfsreq dummyreq;
@@ -446,40 +393,31 @@ nfs_safedisconnect(nmp)
/*
* This is the nfs send routine. For connection based socket types, it
* must be called with an nfs_sndlock() on the socket.
- * "rep == NULL" indicates that it has been called from a server.
- * For the client side:
* - return EINTR if the RPC is terminated, 0 otherwise
* - set R_MUSTRESEND if the send fails for any reason
* - do any cleanup required by recoverable socket errors (?)
- * For the server side:
- * - return EINTR or ERESTART if interrupted by a signal
- * - return EPIPE if a connection is lost for connection based sockets (TCP...)
- * - do any cleanup required by recoverable socket errors (?)
*/
int
-nfs_send(so, nam, top, rep)
- register struct socket *so;
- struct sockaddr *nam;
- register struct mbuf *top;
- struct nfsreq *rep;
+nfs_send(struct socket *so, struct sockaddr *nam, struct mbuf *top,
+ struct nfsreq *rep)
{
struct sockaddr *sendnam;
int error, soflags, flags;
- if (rep) {
- if (rep->r_flags & R_SOFTTERM) {
- m_freem(top);
- return (EINTR);
- }
- if ((so = rep->r_nmp->nm_so) == NULL) {
- rep->r_flags |= R_MUSTRESEND;
- m_freem(top);
- return (0);
- }
- rep->r_flags &= ~R_MUSTRESEND;
- soflags = rep->r_nmp->nm_soflags;
- } else
- soflags = so->so_proto->pr_flags;
+ KASSERT(rep, ("nfs_send: called with rep == NULL"));
+
+ if (rep->r_flags & R_SOFTTERM) {
+ m_freem(top);
+ return (EINTR);
+ }
+ if ((so = rep->r_nmp->nm_so) == NULL) {
+ rep->r_flags |= R_MUSTRESEND;
+ m_freem(top);
+ return (0);
+ }
+ rep->r_flags &= ~R_MUSTRESEND;
+ soflags = rep->r_nmp->nm_soflags;
+
if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
sendnam = (struct sockaddr *)0;
else
@@ -491,29 +429,21 @@ nfs_send(so, nam, top, rep)
error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
flags, curthread /*XXX*/);
- /*
- * ENOBUFS for dgram sockets is transient and non fatal.
- * No need to log, and no need to break a soft mount.
- */
if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
error = 0;
- if (rep) /* do backoff retransmit on client */
- rep->r_flags |= R_MUSTRESEND;
+ rep->r_flags |= R_MUSTRESEND;
}
if (error) {
- if (rep) {
- log(LOG_INFO, "nfs send error %d for server %s\n",error,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- /*
- * Deal with errors for the client side.
- */
- if (rep->r_flags & R_SOFTTERM)
- error = EINTR;
- else
- rep->r_flags |= R_MUSTRESEND;
- } else
- log(LOG_INFO, "nfsd send error %d\n", error);
+ log(LOG_INFO, "nfs send error %d for server %s\n", error,
+ rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
+ /*
+ * Deal with errors for the client side.
+ */
+ if (rep->r_flags & R_SOFTTERM)
+ error = EINTR;
+ else
+ rep->r_flags |= R_MUSTRESEND;
/*
* Handle any recoverable (soft) socket errors here. (?)
@@ -535,15 +465,12 @@ nfs_send(so, nam, top, rep)
* we have read any of it, even if the system call has been interrupted.
*/
static int
-nfs_receive(rep, aname, mp)
- register struct nfsreq *rep;
- struct sockaddr **aname;
- struct mbuf **mp;
+nfs_receive(struct nfsreq *rep, struct sockaddr **aname, struct mbuf **mp)
{
- register struct socket *so;
+ struct socket *so;
struct uio auio;
struct iovec aio;
- register struct mbuf *m;
+ struct mbuf *m;
struct mbuf *control;
u_int32_t len;
struct sockaddr **getnam;
@@ -760,17 +687,16 @@ errout:
* with outstanding requests using the xid, until ours is found.
*/
/* ARGSUSED */
-int
-nfs_reply(myrep)
- struct nfsreq *myrep;
+static int
+nfs_reply(struct nfsreq *myrep)
{
- register struct nfsreq *rep;
- register struct nfsmount *nmp = myrep->r_nmp;
- register int32_t t1;
+ struct nfsreq *rep;
+ struct nfsmount *nmp = myrep->r_nmp;
+ int32_t t1;
struct mbuf *mrep, *md;
struct sockaddr *nam;
u_int32_t rxid, *tl;
- caddr_t dpos, cp2;
+ caddr_t dpos;
int error;
/*
@@ -822,18 +748,8 @@ nfs_reply(myrep)
nfsm_dissect(tl, u_int32_t *, 2*NFSX_UNSIGNED);
rxid = *tl++;
if (*tl != rpc_reply) {
-#ifndef NFS_NOSERVER
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (nqnfs_callback(nmp, mrep, md, dpos))
- nfsstats.rpcinvalid++;
- } else {
- nfsstats.rpcinvalid++;
- m_freem(mrep);
- }
-#else
nfsstats.rpcinvalid++;
m_freem(mrep);
-#endif
nfsmout:
if (myrep->r_flags & R_GETONEREP)
return (0);
@@ -844,31 +760,12 @@ nfsmout:
* Loop through the request list to match up the reply
* Iff no match, just drop the datagram
*/
- for (rep = nfs_reqq.tqh_first; rep != 0;
- rep = rep->r_chain.tqe_next) {
+ TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
if (rep->r_mrep == NULL && rxid == rep->r_xid) {
/* Found it.. */
rep->r_mrep = mrep;
rep->r_md = md;
rep->r_dpos = dpos;
- if (nfsrtton) {
- struct rttl *rt;
-
- rt = &nfsrtt.rttl[nfsrtt.pos];
- rt->proc = rep->r_procnum;
- rt->rto = NFS_RTO(nmp, proct[rep->r_procnum]);
- rt->sent = nmp->nm_sent;
- rt->cwnd = nmp->nm_cwnd;
- rt->srtt = nmp->nm_srtt[proct[rep->r_procnum] - 1];
- rt->sdrtt = nmp->nm_sdrtt[proct[rep->r_procnum] - 1];
- rt->fsid = nmp->nm_mountp->mnt_stat.f_fsid;
- getmicrotime(&rt->tstamp);
- if (rep->r_flags & R_TIMING)
- rt->rtt = rep->r_rtt;
- else
- rt->rtt = 1000000;
- nfsrtt.pos = (nfsrtt.pos + 1) % NFSRTTLOGSIZ;
- }
/*
* Update congestion window.
* Do the additive increase of
@@ -937,34 +834,25 @@ nfsmout:
* by mrep or error
* nb: always frees up mreq mbuf list
*/
+/* XXX overloaded before */
+#define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
+
int
-nfs_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp)
- struct vnode *vp;
- struct mbuf *mrest;
- int procnum;
- struct thread *td;
- struct ucred *cred;
- struct mbuf **mrp;
- struct mbuf **mdp;
- caddr_t *dposp;
+nfs_request(struct vnode *vp, struct mbuf *mrest, int procnum,
+ struct thread *td, struct ucred *cred, struct mbuf **mrp,
+ struct mbuf **mdp, caddr_t *dposp)
{
- register struct mbuf *mrep, *m2;
- register struct nfsreq *rep;
- register u_int32_t *tl;
- register int i;
+ struct mbuf *mrep, *m2;
+ struct nfsreq *rep;
+ u_int32_t *tl;
+ int i;
struct nfsmount *nmp;
struct mbuf *m, *md, *mheadend;
- struct nfsnode *np;
- char nickv[RPCX_NICKVERF];
- time_t reqtime, waituntil;
- caddr_t dpos, cp2;
- int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
- int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
- int verf_len, verf_type;
+ time_t waituntil;
+ caddr_t dpos;
+ int s, error = 0, mrest_len, auth_len, auth_type;
+ int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0;
u_int32_t xid;
- u_quad_t frev;
- char *auth_str, *verf_str;
- NFSKERBKEY_T key; /* save session key */
nmp = VFSTONFS(vp->v_mount);
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
@@ -983,35 +871,14 @@ nfs_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp)
/*
* Get the RPC header with authorization.
*/
-kerbauth:
- verf_str = auth_str = (char *)0;
- if (nmp->nm_flag & NFSMNT_KERB) {
- verf_str = nickv;
- verf_len = sizeof (nickv);
- auth_type = RPCAUTH_KERB4;
- bzero((caddr_t)key, sizeof (key));
- if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
- &auth_len, verf_str, verf_len)) {
- error = nfs_getauth(nmp, rep, cred, &auth_str,
- &auth_len, verf_str, &verf_len, key);
- if (error) {
- free((caddr_t)rep, M_NFSREQ);
- m_freem(mrest);
- return (error);
- }
- }
- } else {
- auth_type = RPCAUTH_UNIX;
- if (cred->cr_ngroups < 1)
- panic("nfsreq nogrps");
- auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
- nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
- 5 * NFSX_UNSIGNED;
- }
+ auth_type = RPCAUTH_UNIX;
+ if (cred->cr_ngroups < 1)
+ panic("nfsreq nogrps");
+ auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
+ nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
+ 5 * NFSX_UNSIGNED;
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
- auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
- if (auth_str)
- free(auth_str, M_TEMP);
+ mrest, mrest_len, &mheadend, &xid);
/*
* For stream protocols, insert a Sun RPC Record Mark.
@@ -1046,9 +913,6 @@ tryagain:
s = splsoftclock();
TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain);
- /* Get send time for nqnfs */
- reqtime = time_second;
-
/*
* If backing off another request or avoiding congestion, don't
* send this one now but let timer do it. If not timing a request,
@@ -1119,16 +983,7 @@ tryagain:
if (*tl++ == rpc_msgdenied) {
if (*tl == rpc_mismatch)
error = EOPNOTSUPP;
- else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
- if (!failed_auth) {
- failed_auth++;
- mheadend->m_next = (struct mbuf *)0;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- goto kerbauth;
- } else
- error = EAUTH;
- } else
+ else
error = EACCES;
m_freem(mrep);
m_freem(rep->r_mreq);
@@ -1137,15 +992,11 @@ tryagain:
}
/*
- * Grab any Kerberos verifier, otherwise just throw it away.
+ * Just throw away any verifyer (ie: kerberos etc).
*/
- verf_type = fxdr_unsigned(int, *tl++);
- i = fxdr_unsigned(int32_t, *tl);
- if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
- error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
- if (error)
- goto nfsmout;
- } else if (i > 0)
+ i = fxdr_unsigned(int, *tl++); /* verf type */
+ i = fxdr_unsigned(int32_t, *tl); /* len */
+ if (i > 0)
nfsm_adv(nfsm_rndup(i));
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
/* 0 == ok */
@@ -1185,24 +1036,6 @@ tryagain:
return (error);
}
- /*
- * For nqnfs, get any lease in reply
- */
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl) {
- np = VTONFS(vp);
- nqlflag = fxdr_unsigned(int, *tl);
- nfsm_dissect(tl, u_int32_t *, 4*NFSX_UNSIGNED);
- cachable = fxdr_unsigned(int, *tl++);
- reqtime += fxdr_unsigned(int, *tl++);
- if (reqtime > time_second) {
- frev = fxdr_hyper(tl);
- nqnfs_clientlease(nmp, np, nqlflag,
- cachable, reqtime, frev);
- }
- }
- }
*mrp = mrep;
*mdp = md;
*dposp = dpos;
@@ -1218,162 +1051,6 @@ nfsmout:
return (error);
}
-#ifndef NFS_NOSERVER
-/*
- * Generate the rpc reply header
- * siz arg. is used to decide if adding a cluster is worthwhile
- */
-int
-nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
- int siz;
- struct nfsrv_descript *nd;
- struct nfssvc_sock *slp;
- int err;
- int cache;
- u_quad_t *frev;
- struct mbuf **mrq;
- struct mbuf **mbp;
- caddr_t *bposp;
-{
- register u_int32_t *tl;
- register struct mbuf *mreq;
- caddr_t bpos;
- struct mbuf *mb, *mb2;
-
- MGETHDR(mreq, M_TRYWAIT, MT_DATA);
- mb = mreq;
- /*
- * If this is a big reply, use a cluster else
- * try and leave leading space for the lower level headers.
- */
- siz += RPC_REPLYSIZ;
- if ((max_hdr + siz) >= MINCLSIZE) {
- MCLGET(mreq, M_TRYWAIT);
- } else
- mreq->m_data += max_hdr;
- tl = mtod(mreq, u_int32_t *);
- mreq->m_len = 6 * NFSX_UNSIGNED;
- bpos = ((caddr_t)tl) + mreq->m_len;
- *tl++ = txdr_unsigned(nd->nd_retxid);
- *tl++ = rpc_reply;
- if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
- *tl++ = rpc_msgdenied;
- if (err & NFSERR_AUTHERR) {
- *tl++ = rpc_autherr;
- *tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
- mreq->m_len -= NFSX_UNSIGNED;
- bpos -= NFSX_UNSIGNED;
- } else {
- *tl++ = rpc_mismatch;
- *tl++ = txdr_unsigned(RPC_VER2);
- *tl = txdr_unsigned(RPC_VER2);
- }
- } else {
- *tl++ = rpc_msgaccepted;
-
- /*
- * For Kerberos authentication, we must send the nickname
- * verifier back, otherwise just RPCAUTH_NULL.
- */
- if (nd->nd_flag & ND_KERBFULL) {
- register struct nfsuid *nuidp;
- struct timeval ktvin, ktvout;
-
- for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
- (!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (nuidp) {
- ktvin.tv_sec =
- txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
- ktvin.tv_usec =
- txdr_unsigned(nuidp->nu_timestamp.tv_usec);
-
- /*
- * Encrypt the timestamp in ecb mode using the
- * session key.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- *tl++ = rpc_auth_kerb;
- *tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
- *tl = ktvout.tv_sec;
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- *tl++ = ktvout.tv_usec;
- *tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
- switch (err) {
- case EPROGUNAVAIL:
- *tl = txdr_unsigned(RPC_PROGUNAVAIL);
- break;
- case EPROGMISMATCH:
- *tl = txdr_unsigned(RPC_PROGMISMATCH);
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (nd->nd_flag & ND_NQNFS) {
- *tl++ = txdr_unsigned(3);
- *tl = txdr_unsigned(3);
- } else {
- *tl++ = txdr_unsigned(2);
- *tl = txdr_unsigned(3);
- }
- break;
- case EPROCUNAVAIL:
- *tl = txdr_unsigned(RPC_PROCUNAVAIL);
- break;
- case EBADRPC:
- *tl = txdr_unsigned(RPC_GARBAGE);
- break;
- default:
- *tl = 0;
- if (err != NFSERR_RETVOID) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- if (err)
- *tl = txdr_unsigned(nfsrv_errmap(nd, err));
- else
- *tl = 0;
- }
- break;
- };
- }
-
- /*
- * For nqnfs, piggyback lease as requested.
- */
- if ((nd->nd_flag & ND_NQNFS) && err == 0) {
- if (nd->nd_flag & ND_LEASE) {
- nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
- *tl++ = txdr_unsigned(cache);
- *tl++ = txdr_unsigned(nd->nd_duration);
- txdr_hyper(*frev, tl);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
- if (mrq != NULL)
- *mrq = mreq;
- *mbp = mb;
- *bposp = bpos;
- if (err != 0 && err != NFSERR_RETVOID)
- nfsstats.srvrpc_errs++;
- return (0);
-}
-
-
-#endif /* NFS_NOSERVER */
/*
* Nfs timer routine
* Scan the nfsreq list and retranmit any requests that have timed out
@@ -1381,24 +1058,18 @@ nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
* sure to set the r_retry field to 0 (implies nm_retry == 0).
*/
void
-nfs_timer(arg)
- void *arg; /* never used */
+nfs_timer(void *arg)
{
- register struct nfsreq *rep;
- register struct mbuf *m;
- register struct socket *so;
- register struct nfsmount *nmp;
- register int timeo;
+ struct nfsreq *rep;
+ struct mbuf *m;
+ struct socket *so;
+ struct nfsmount *nmp;
+ int timeo;
int s, error;
-#ifndef NFS_NOSERVER
- static long lasttime = 0;
- register struct nfssvc_sock *slp;
- u_quad_t cur_usec;
-#endif /* NFS_NOSERVER */
struct thread *td = thread0; /* XXX for credentials, will break if sleep */
s = splnet();
- for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
+ TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
nmp = rep->r_nmp;
if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
continue;
@@ -1425,9 +1096,12 @@ nfs_timer(arg)
*/
if ((rep->r_flags & R_TPRINTFMSG) == 0 &&
rep->r_rexmit > nmp->nm_deadthresh) {
+ char buf[40];
+ sprintf(buf, "not responding %d > %d",
+ rep->r_rexmit, nmp->nm_deadthresh);
nfs_msg(rep->r_td,
nmp->nm_mountp->mnt_stat.f_mntfromname,
- "not responding");
+ buf /* "not responding" */);
rep->r_flags |= R_TPRINTFMSG;
}
if (rep->r_rexmit >= rep->r_retry) { /* too many */
@@ -1487,26 +1161,6 @@ nfs_timer(arg)
}
}
}
-#ifndef NFS_NOSERVER
- /*
- * Call the nqnfs server timer once a second to handle leases.
- */
- if (lasttime != time_second) {
- lasttime = time_second;
- nqnfs_serverd();
- }
-
- /*
- * Scan the write gathering queues for writes that need to be
- * completed now.
- */
- cur_usec = nfs_curusec();
- for (slp = nfssvc_sockhead.tqh_first; slp != 0;
- slp = slp->ns_chain.tqe_next) {
- if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
- nfsrv_wakenfsd(slp);
- }
-#endif /* NFS_NOSERVER */
splx(s);
nfs_timer_handle = timeout(nfs_timer, (void *)0, nfs_ticks);
}
@@ -1518,11 +1172,10 @@ nfs_timer(arg)
*/
static void
-nfs_softterm(rep)
- struct nfsreq *rep;
+nfs_softterm(struct nfsreq *rep)
{
- rep->r_flags |= R_SOFTTERM;
+ rep->r_flags |= R_SOFTTERM;
if (rep->r_flags & R_SENT) {
rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
rep->r_flags &= ~R_SENT;
@@ -1534,10 +1187,7 @@ nfs_softterm(rep)
* This is used for NFSMNT_INT mounts.
*/
int
-nfs_sigintr(nmp, rep, p)
- struct nfsmount *nmp;
- struct nfsreq *rep;
- register struct proc *p;
+nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct proc *p)
{
sigset_t tmpset;
@@ -1564,10 +1214,9 @@ nfs_sigintr(nmp, rep, p)
* in progress when a reconnect is necessary.
*/
int
-nfs_sndlock(rep)
- struct nfsreq *rep;
+nfs_sndlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
struct thread *td;
int slpflag = 0, slptimeo = 0;
@@ -1596,10 +1245,9 @@ nfs_sndlock(rep)
* Unlock the stream socket for others.
*/
void
-nfs_sndunlock(rep)
- struct nfsreq *rep;
+nfs_sndunlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
if ((*statep & NFSSTA_SNDLOCK) == 0)
panic("nfs sndunlock");
@@ -1611,10 +1259,9 @@ nfs_sndunlock(rep)
}
static int
-nfs_rcvlock(rep)
- register struct nfsreq *rep;
+nfs_rcvlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
int slpflag, slptimeo = 0;
if (rep->r_nmp->nm_flag & NFSMNT_INT)
@@ -1649,10 +1296,9 @@ nfs_rcvlock(rep)
* Unlock the stream socket for others.
*/
static void
-nfs_rcvunlock(rep)
- register struct nfsreq *rep;
+nfs_rcvunlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
if ((*statep & NFSSTA_RCVLOCK) == 0)
panic("nfs rcvunlock");
@@ -1679,16 +1325,13 @@ nfs_rcvunlock(rep)
* with TCP. Use vfs.nfs.realign_count and realign_test to check this.
*/
static void
-nfs_realign(pm, hsiz)
- register struct mbuf **pm;
- int hsiz;
+nfs_realign(struct mbuf **pm, int hsiz)
{
struct mbuf *m;
struct mbuf *n = NULL;
int off = 0;
++nfs_realign_test;
-
while ((m = *pm) != NULL) {
if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
MGET(n, M_TRYWAIT, MT_DATA);
@@ -1700,7 +1343,6 @@ nfs_realign(pm, hsiz)
}
pm = &m->m_next;
}
-
/*
* If n is non-NULL, loop on m copying data, then replace the
* portion of the chain that had to be realigned.
@@ -1717,580 +1359,11 @@ nfs_realign(pm, hsiz)
}
}
-#ifndef NFS_NOSERVER
-
-/*
- * Parse an RPC request
- * - verify it
- * - fill in the cred struct.
- */
-int
-nfs_getreq(nd, nfsd, has_header)
- register struct nfsrv_descript *nd;
- struct nfsd *nfsd;
- int has_header;
-{
- register int len, i;
- register u_int32_t *tl;
- register int32_t t1;
- struct uio uio;
- struct iovec iov;
- caddr_t dpos, cp2, cp;
- u_int32_t nfsvers, auth_type;
- uid_t nickuid;
- int error = 0, nqnfs = 0, ticklen;
- struct mbuf *mrep, *md;
- register struct nfsuid *nuidp;
- struct timeval tvin, tvout;
-#if 0 /* until encrypted keys are implemented */
- NFSKERBKEYSCHED_T keys; /* stores key schedule */
-#endif
-
- mrep = nd->nd_mrep;
- md = nd->nd_md;
- dpos = nd->nd_dpos;
- if (has_header) {
- nfsm_dissect(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
- nd->nd_retxid = fxdr_unsigned(u_int32_t, *tl++);
- if (*tl++ != rpc_call) {
- m_freem(mrep);
- return (EBADRPC);
- }
- } else
- nfsm_dissect(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
- nd->nd_repstat = 0;
- nd->nd_flag = 0;
- if (*tl++ != rpc_vers) {
- nd->nd_repstat = ERPCMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if (*tl != nfs_prog) {
- if (*tl == nqnfs_prog)
- nqnfs++;
- else {
- nd->nd_repstat = EPROGUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- }
- tl++;
- nfsvers = fxdr_unsigned(u_int32_t, *tl++);
- if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
- (nfsvers != NQNFS_VER3 && nqnfs)) {
- nd->nd_repstat = EPROGMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if (nqnfs)
- nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
- else if (nfsvers == NFS_VER3)
- nd->nd_flag = ND_NFSV3;
- nd->nd_procnum = fxdr_unsigned(u_int32_t, *tl++);
- if (nd->nd_procnum == NFSPROC_NULL)
- return (0);
- if (nd->nd_procnum >= NFS_NPROCS ||
- (!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
- (!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
- nd->nd_repstat = EPROCUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if ((nd->nd_flag & ND_NFSV3) == 0)
- nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
- auth_type = *tl++;
- len = fxdr_unsigned(int, *tl++);
- if (len < 0 || len > RPCAUTH_MAXSIZ) {
- m_freem(mrep);
- return (EBADRPC);
- }
-
- nd->nd_flag &= ~ND_KERBAUTH;
- /*
- * Handle auth_unix or auth_kerb.
- */
- if (auth_type == rpc_auth_unix) {
- len = fxdr_unsigned(int, *++tl);
- if (len < 0 || len > NFS_MAXNAMLEN) {
- m_freem(mrep);
- return (EBADRPC);
- }
- nfsm_adv(nfsm_rndup(len));
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
- nd->nd_cr.cr_ref = 1;
- nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
- nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
- len = fxdr_unsigned(int, *tl);
- if (len < 0 || len > RPCAUTH_UNIXGIDS) {
- m_freem(mrep);
- return (EBADRPC);
- }
- nfsm_dissect(tl, u_int32_t *, (len + 2) * NFSX_UNSIGNED);
- for (i = 1; i <= len; i++)
- if (i < NGROUPS)
- nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
- else
- tl++;
- nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
- if (nd->nd_cr.cr_ngroups > 1)
- nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
- len = fxdr_unsigned(int, *++tl);
- if (len < 0 || len > RPCAUTH_MAXSIZ) {
- m_freem(mrep);
- return (EBADRPC);
- }
- if (len > 0)
- nfsm_adv(nfsm_rndup(len));
- } else if (auth_type == rpc_auth_kerb) {
- switch (fxdr_unsigned(int, *tl++)) {
- case RPCAKN_FULLNAME:
- ticklen = fxdr_unsigned(int, *tl);
- *((u_int32_t *)nfsd->nfsd_authstr) = *tl;
- uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
- nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
- if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
- m_freem(mrep);
- return (EBADRPC);
- }
- uio.uio_offset = 0;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_segflg = UIO_SYSSPACE;
- iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
- iov.iov_len = RPCAUTH_MAXSIZ - 4;
- nfsm_mtouio(&uio, uio.uio_resid);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
- printf("Bad kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
- tl = (u_int32_t *)cp;
- if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
- printf("Not fullname kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- cp += NFSX_UNSIGNED;
- bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
- nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
- nd->nd_flag |= ND_KERBFULL;
- nfsd->nfsd_flag |= NFSD_NEEDAUTH;
- break;
- case RPCAKN_NICKNAME:
- if (len != 2 * NFSX_UNSIGNED) {
- printf("Kerb nickname short\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nickuid = fxdr_unsigned(uid_t, *tl);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
- printf("Kerb nick verifier bad\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- tvin.tv_sec = *tl++;
- tvin.tv_usec = *tl;
-
- for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nickuid &&
- (!nd->nd_nam2 ||
- netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (!nuidp) {
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- /*
- * Now, decrypt the timestamp using the session key
- * and validate it.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
- tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
- if (nuidp->nu_expire < time_second ||
- nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
- (nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
- nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
- nuidp->nu_expire = 0;
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
- nd->nd_flag |= ND_KERBNICK;
- };
- } else {
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- /*
- * For nqnfs, get piggybacked lease request.
- */
- if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_flag |= fxdr_unsigned(int, *tl);
- if (nd->nd_flag & ND_LEASE) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_duration = fxdr_unsigned(int32_t, *tl);
- } else
- nd->nd_duration = NQ_MINLEASE;
- } else
- nd->nd_duration = NQ_MINLEASE;
- nd->nd_md = md;
- nd->nd_dpos = dpos;
- return (0);
-nfsmout:
- return (error);
-}
-
-#endif
static int
-nfs_msg(td, server, msg)
- struct thread *td;
- char *server, *msg;
+nfs_msg(struct thread *td, char *server, char *msg)
{
tprintf(td->td_proc, LOG_INFO, "nfs server %s: %s\n", server, msg);
return (0);
}
-
-#ifndef NFS_NOSERVER
-/*
- * Socket upcall routine for the nfsd sockets.
- * The caddr_t arg is a pointer to the "struct nfssvc_sock".
- * Essentially do as much as possible non-blocking, else punt and it will
- * be called with M_TRYWAIT from an nfsd.
- */
-void
-nfsrv_rcv(so, arg, waitflag)
- struct socket *so;
- void *arg;
- int waitflag;
-{
- register struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
- register struct mbuf *m;
- struct mbuf *mp;
- struct sockaddr *nam;
- struct uio auio;
- int flags, error;
-
- if ((slp->ns_flag & SLP_VALID) == 0)
- return;
-#ifdef notdef
- /*
- * Define this to test for nfsds handling this under heavy load.
- */
- if (waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ; goto dorecs;
- }
-#endif
- auio.uio_td = NULL;
- if (so->so_type == SOCK_STREAM) {
- /*
- * If there are already records on the queue, defer soreceive()
- * to an nfsd so that there is feedback to the TCP layer that
- * the nfs servers are heavily loaded.
- */
- if (STAILQ_FIRST(&slp->ns_rec) && waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ;
- goto dorecs;
- }
-
- /*
- * Do soreceive().
- */
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, &nam, &auio, &mp, (struct mbuf **)0, &flags);
- if (error || mp == (struct mbuf *)0) {
- if (error == EWOULDBLOCK)
- slp->ns_flag |= SLP_NEEDQ;
- else
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- m = mp;
- if (slp->ns_rawend) {
- slp->ns_rawend->m_next = m;
- slp->ns_cc += 1000000000 - auio.uio_resid;
- } else {
- slp->ns_raw = m;
- slp->ns_cc = 1000000000 - auio.uio_resid;
- }
- while (m->m_next)
- m = m->m_next;
- slp->ns_rawend = m;
-
- /*
- * Now try and parse record(s) out of the raw stream data.
- */
- error = nfsrv_getstream(slp, waitflag);
- if (error) {
- if (error == EPERM)
- slp->ns_flag |= SLP_DISCONN;
- else
- slp->ns_flag |= SLP_NEEDQ;
- }
- } else {
- do {
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, &nam, &auio, &mp,
- (struct mbuf **)0, &flags);
- if (mp) {
- struct nfsrv_rec *rec;
- rec = malloc(sizeof(struct nfsrv_rec),
- M_NFSRVDESC, waitflag);
- if (!rec) {
- if (nam)
- FREE(nam, M_SONAME);
- m_freem(mp);
- continue;
- }
- nfs_realign(&mp, 10 * NFSX_UNSIGNED);
- rec->nr_address = nam;
- rec->nr_packet = mp;
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- }
- if (error) {
- if ((so->so_proto->pr_flags & PR_CONNREQUIRED)
- && error != EWOULDBLOCK) {
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- }
- } while (mp);
- }
-
- /*
- * Now try and process the request records, non-blocking.
- */
-dorecs:
- if (waitflag == M_DONTWAIT &&
- (STAILQ_FIRST(&slp->ns_rec)
- || (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN))))
- nfsrv_wakenfsd(slp);
-}
-
-/*
- * Try and extract an RPC request from the mbuf data list received on a
- * stream socket. The "waitflag" argument indicates whether or not it
- * can sleep.
- */
-static int
-nfsrv_getstream(slp, waitflag)
- register struct nfssvc_sock *slp;
- int waitflag;
-{
- register struct mbuf *m, **mpp;
- register char *cp1, *cp2;
- register int len;
- struct mbuf *om, *m2, *recm = NULL;
- u_int32_t recmark;
-
- if (slp->ns_flag & SLP_GETSTREAM)
- panic("nfs getstream");
- slp->ns_flag |= SLP_GETSTREAM;
- for (;;) {
- if (slp->ns_reclen == 0) {
- if (slp->ns_cc < NFSX_UNSIGNED) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
- m = slp->ns_raw;
- if (m->m_len >= NFSX_UNSIGNED) {
- bcopy(mtod(m, caddr_t), (caddr_t)&recmark, NFSX_UNSIGNED);
- m->m_data += NFSX_UNSIGNED;
- m->m_len -= NFSX_UNSIGNED;
- } else {
- cp1 = (caddr_t)&recmark;
- cp2 = mtod(m, caddr_t);
- while (cp1 < ((caddr_t)&recmark) + NFSX_UNSIGNED) {
- while (m->m_len == 0) {
- m = m->m_next;
- cp2 = mtod(m, caddr_t);
- }
- *cp1++ = *cp2++;
- m->m_data++;
- m->m_len--;
- }
- }
- slp->ns_cc -= NFSX_UNSIGNED;
- recmark = ntohl(recmark);
- slp->ns_reclen = recmark & ~0x80000000;
- if (recmark & 0x80000000)
- slp->ns_flag |= SLP_LASTFRAG;
- else
- slp->ns_flag &= ~SLP_LASTFRAG;
- if (slp->ns_reclen > NFS_MAXPACKET) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EPERM);
- }
- }
-
- /*
- * Now get the record part.
- */
- if (slp->ns_cc == slp->ns_reclen) {
- recm = slp->ns_raw;
- slp->ns_raw = slp->ns_rawend = (struct mbuf *)0;
- slp->ns_cc = slp->ns_reclen = 0;
- } else if (slp->ns_cc > slp->ns_reclen) {
- len = 0;
- m = slp->ns_raw;
- om = (struct mbuf *)0;
- while (len < slp->ns_reclen) {
- if ((len + m->m_len) > slp->ns_reclen) {
- m2 = m_copym(m, 0, slp->ns_reclen - len,
- waitflag);
- if (m2) {
- if (om) {
- om->m_next = m2;
- recm = slp->ns_raw;
- } else
- recm = m2;
- m->m_data += slp->ns_reclen - len;
- m->m_len -= slp->ns_reclen - len;
- len = slp->ns_reclen;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EWOULDBLOCK);
- }
- } else if ((len + m->m_len) == slp->ns_reclen) {
- om = m;
- len += m->m_len;
- m = m->m_next;
- recm = slp->ns_raw;
- om->m_next = (struct mbuf *)0;
- } else {
- om = m;
- len += m->m_len;
- m = m->m_next;
- }
- }
- slp->ns_raw = m;
- slp->ns_cc -= len;
- slp->ns_reclen = 0;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
-
- /*
- * Accumulate the fragments into a record.
- */
- mpp = &slp->ns_frag;
- while (*mpp)
- mpp = &((*mpp)->m_next);
- *mpp = recm;
- if (slp->ns_flag & SLP_LASTFRAG) {
- struct nfsrv_rec *rec;
- rec = malloc(sizeof(struct nfsrv_rec), M_NFSRVDESC, waitflag);
- if (!rec) {
- m_freem(slp->ns_frag);
- } else {
- nfs_realign(&slp->ns_frag, 10 * NFSX_UNSIGNED);
- rec->nr_address = (struct sockaddr *)0;
- rec->nr_packet = slp->ns_frag;
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- }
- slp->ns_frag = (struct mbuf *)0;
- }
- }
-}
-
-/*
- * Parse an RPC header.
- */
-int
-nfsrv_dorec(slp, nfsd, ndp)
- register struct nfssvc_sock *slp;
- struct nfsd *nfsd;
- struct nfsrv_descript **ndp;
-{
- struct nfsrv_rec *rec;
- register struct mbuf *m;
- struct sockaddr *nam;
- register struct nfsrv_descript *nd;
- int error;
-
- *ndp = NULL;
- if ((slp->ns_flag & SLP_VALID) == 0 || !STAILQ_FIRST(&slp->ns_rec))
- return (ENOBUFS);
- rec = STAILQ_FIRST(&slp->ns_rec);
- STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
- nam = rec->nr_address;
- m = rec->nr_packet;
- free(rec, M_NFSRVDESC);
- MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
- M_NFSRVDESC, M_WAITOK);
- nd->nd_md = nd->nd_mrep = m;
- nd->nd_nam2 = nam;
- nd->nd_dpos = mtod(m, caddr_t);
- error = nfs_getreq(nd, nfsd, TRUE);
- if (error) {
- if (nam) {
- FREE(nam, M_SONAME);
- }
- free((caddr_t)nd, M_NFSRVDESC);
- return (error);
- }
- *ndp = nd;
- nfsd->nfsd_nd = nd;
- return (0);
-}
-
-/*
- * Search for a sleeping nfsd and wake it up.
- * SIDE EFFECT: If none found, set NFSD_CHECKSLP flag, so that one of the
- * running nfsds will go look for the work in the nfssvc_sock list.
- */
-void
-nfsrv_wakenfsd(slp)
- struct nfssvc_sock *slp;
-{
- register struct nfsd *nd;
-
- if ((slp->ns_flag & SLP_VALID) == 0)
- return;
- for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
- if (nd->nfsd_flag & NFSD_WAITING) {
- nd->nfsd_flag &= ~NFSD_WAITING;
- if (nd->nfsd_slp)
- panic("nfsd wakeup");
- slp->ns_sref++;
- nd->nfsd_slp = slp;
- wakeup((caddr_t)nd);
- return;
- }
- }
- slp->ns_flag |= SLP_DOREC;
- nfsd_head_flag |= NFSD_CHECKSLP;
-}
-#endif /* NFS_NOSERVER */
OpenPOWER on IntegriCloud