NFS just finished a major weight reduction program

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4838 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2012-06-14 00:47:42 +00:00
parent 8764f673f2
commit c0c2a8b2df
15 changed files with 473 additions and 1003 deletions

View File

@@ -98,23 +98,6 @@
* Pre-processor Definitions
****************************************************************************/
/* There is a congestion window for outstanding RPCs maintained per mount
* point. The cwnd size is adjusted in roughly the way that: Van Jacobson,
* Congestion avoidance and Control, In "Proceedings of SIGCOMM '88". ACM,
* August 1988. describes for TCP. The cwnd size is chopped in half on a
* retransmit timeout and incremented by 1/cwnd when each RPC reply is
* received and a full cwnd of RPCs is in progress. (The sent count and cwnd
* are scaled for integer arith.) Variants of "slow start" were tried and
* were found to be too much of a performance hit (ave. rtt 3 times larger),
* I suspect due to the large rtt that nfs RPCs have.
*/
#define RPC_CWNDSCALE 256
#define RPC_MAXCWND (RPC_CWNDSCALE * 32)
#define RPC_ERRSTR_ACCEPTED_SIZE 6
#define RPC_ERRSTR_AUTH_SIZE 6
/* Increment RPC statistics */
#ifdef CONFIG_NFS_STATISTICS
@@ -159,9 +142,6 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname,
int proc, int program, void *reply, size_t resplen);
static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
void *reply, size_t resplen);
#ifdef CONFIG_NFS_TCPIP
static int rpcclnt_reconnect(FAR struct rpcclnt *rpc);
#endif
static uint32_t rpcclnt_newxid(void);
static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
uint32_t xid, int procid, int prog, int vers);
@@ -221,208 +201,19 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname,
int proc, int program, void *reply, size_t resplen)
{
ssize_t nbytes;
#ifdef CONFIG_NFS_TCPIP
uint32_t resplen;
int sotype;
#endif
int error = 0;
int errval;
#ifdef CONFIG_NFS_TCPIP
/* Set up arguments for psock_recvfrom() */
sotype = rpc->rc_sotype;
if (sotype != SOCK_DGRAM)
if (rpc->rc_so == NULL)
{
tryagain:
/* Check for fatal errors and resending request. */
if (rpc->rc_so == NULL)
{
error = rpcclnt_reconnect(rpc);
if (error)
{
return error;
}
goto tryagain;
}
while (rpc->rc_callflags & RPCCALL_MUSTRESEND)
{
rpc_statistics(rpcretries);
error = rpcclnt_send(rpc, proc, program, call, reqlen);
if (error)
{
if (error == EINTR || error == ERESTART)
{
return error;
}
error = rpcclnt_reconnect(rpc);
if (error != OK)
{
return error;
}
goto tryagain;
}
}
if (sotype == SOCK_STREAM)
{
errval = 0;
do
{
socklen_t fromlen = sizeof(*rpc->rc_name)
nbytes = psock_recvfrom(rpc->rc_so, reply, resplen,
MSG_WAITALL, rpc->rc_name,
&fromlen);
if (nbytes < 0)
{
errval = errno;
fdbg("ERROR: psock_recvfrom returned %d\n", errval);
}
}
while (errval == EWOULDBLOCK);
if (nbytes < 0)
{
error = errval;
}
else if (nbytes < resplen)
{
fdbg("ERROR: Short receive from RPC server\n");
fvdbg(" Expected %d bytes, received %d bytes\n",
resplen, nbytes);
error = EPIPE;
}
else
{
error = 0;
}
#warning "What is resplen? This logic is not right!"
resplen = ntohl(resplen) & ~0x80000000;
/* This is SERIOUS! We are out of sync with the
* sender and forcing a disconnect/reconnect is all I
* can do.
*/
else if (resplen > RPC_MAXPACKET)
{
fdbg("ERROR: Impossible length rom RPC server: %d\n", resplen);
error = EFBIG;
goto errout;
}
errval = 0
do
{
socklen_t fromlen = sizeof(*rpc->rc_name);
nbytes = psock_recvfrom(so, reply, sizeof(*reply),
MSG_WAITALL, rpc->rc_name,
&fromlen);
if (nbytes < 0)
{
errval = errno;
fdbg("ERROR: psock_recvfrom failed: %d\n", errval);
}
}
while (errval == EWOULDBLOCK || errval == EINTR || errval == ERESTART);
if (nbytes < 0)
{
error = errval;
goto errout;
}
else if (nbytes < resplen)
{
fdbg("ERROR: Short receive from RPC server\n");
fvdbg(" Expected %d bytes, received %d bytes\n",
resplen, nbytes);
error = EPIPE;
}
else
{
error = 0;
}
}
else
{
/* NB: Since uio_resid is big, MSG_WAITALL is ignored
* and psock_recvfrom() will return when it has either a
* control msg or a data msg. We have no use for
* control msg., but must grab them and then throw
* them away so we know what is going on.
*/
errval = 0;
do
{
socklen_t fromlen = sizeof(*rpc->rc_name);
nbytes = psock_recvfrom(so, reply, sizeof(*reply), 0,
rpc->rc_name, &fromlen);
if (nbytes < 0)
{
errval = errno;
fdbg("ERROR: psock_recvfrom failed: %d\n", errval);
}
}
while (errval == EWOULDBLOCK || nbytes == 0);
if (nbytes < 0)
{
error = errval;
goto errout;
}
else if (nbytes < resplen)
{
fdbg("ERROR: Short receive from RPC server\n");
fvdbg(" Expected %d bytes, received %d bytes\n",
resplen, nbytes);
error = EPIPE;
}
else
{
error = 0;
}
}
errout:
if (error != 0 && error != EINTR && error != ERESTART)
{
if (error != EPIPE)
{
fdbg("ERROR: Receive error %d from RPC server\n", error);
}
error = rpcclnt_reconnect(rpc);
if (error == 0)
{
goto tryagain;
}
}
return EACCES;
}
else
#endif
{
if (rpc->rc_so == NULL)
{
return EACCES;
}
socklen_t fromlen = sizeof(struct sockaddr);
nbytes = psock_recvfrom(rpc->rc_so, reply, resplen, 0, aname, &fromlen);
if (nbytes < 0)
{
errval = errno;
fdbg("ERROR: psock_recvfrom failed: %d\n", errval);
error = errval;
}
socklen_t fromlen = sizeof(struct sockaddr);
nbytes = psock_recvfrom(rpc->rc_so, reply, resplen, 0, aname, &fromlen);
if (nbytes < 0)
{
error = errno;
fdbg("ERROR: psock_recvfrom failed: %d\n", error);
}
return error;
@@ -467,7 +258,7 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
replyheader = (FAR struct rpc_reply_header *)reply;
rxid = replyheader->rp_xid;
if (replyheader->rp_direction != rpc_reply)
{
rpc_statistics(rpcinvalid);
@@ -522,7 +313,7 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
uint32_t xid, int prog, int vers, int procid)
{
/* Format the call header */
ch->rp_xid = txdr_unsigned(xid);
ch->rp_direction = rpc_call;
ch->rp_rpcvers = rpc_vers;
@@ -535,14 +326,6 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch,
ch->rpc_auth.authtype = rpc_auth_null;
ch->rpc_auth.authlen = 0;
#ifdef CONFIG_NFS_UNIX_AUTH
ch->rpc_unix.stamp = txdr_unsigned(1);
ch->rpc_unix.hostname = 0;
ch->rpc_unix.uid = setuid;
ch->rpc_unix.gid = setgid;
ch->rpc_unix.gidlist = 0;
#endif
/* rpc_verf part (auth_null) */
ch->rpc_verf.authtype = rpc_auth_null;
@@ -594,7 +377,6 @@ int rpcclnt_connect(struct rpcclnt *rpc)
/* Create the socket */
saddr = rpc->rc_name;
memset(&sin, 0, sizeof(sin));
/* Create an instance of the socket state structure */
@@ -605,7 +387,7 @@ int rpcclnt_connect(struct rpcclnt *rpc)
return ENOMEM;
}
error = psock_socket(saddr->sa_family, rpc->rc_sotype, rpc->rc_soproto, so);
error = psock_socket(saddr->sa_family, rpc->rc_sotype, IPPROTO_UDP, so);
if (error < 0)
{
errval = errno;
@@ -678,8 +460,6 @@ int rpcclnt_connect(struct rpcclnt *rpc)
* Get port number for MOUNTD.
*/
memset(&sdata, 0, sizeof(struct rpc_call_pmap));
memset(&rdata, 0, sizeof(struct rpc_reply_pmap));
sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT);
sdata.pmap.vers = txdr_unsigned(RPCMNT_VER1);
sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP);
@@ -707,8 +487,6 @@ int rpcclnt_connect(struct rpcclnt *rpc)
/* Do RPC to mountd. */
memset(&mountd, 0, sizeof(struct rpc_call_mount));
memset(&mdata, 0, sizeof(struct rpc_reply_mount));
strncpy(mountd.mount.rpath, rpc->rc_path, 90);
mountd.mount.len = txdr_unsigned(sizeof(mountd.mount.rpath));
@@ -734,8 +512,6 @@ int rpcclnt_connect(struct rpcclnt *rpc)
* NFS port in the socket.
*/
memset(&sdata, 0, sizeof(struct rpc_call_pmap));
memset(&rdata, 0, sizeof(struct rpc_reply_pmap));
sa->sin_port = htons(PMAPPORT);
error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
@@ -776,35 +552,6 @@ bad:
return error;
}
/* Reconnect routine: Called when a connection is broken on a reliable
* protocol. - clean up the old socket - nfs_connect() again - set
* RPCCALL_MUSTRESEND for all outstanding requests on mount point If this
* fails the mount point is DEAD!
*/
#ifdef CONFIG_NFS_TCPIP
int rpcclnt_reconnect(FAR struct rpcclnt *rpc)
{
int error;
rpcclnt_disconnect(rpc);
do
{
error = rpcclnt_connect(rpc);
if (error != OK)
{
fdbg("ERROR: rpcclnt_connect failed: %d\n", error);
if (error == EINTR || error == ERESTART)
{
return EINTR;
}
}
}
while (error != OK)
return OK;
}
#endif
void rpcclnt_disconnect(struct rpcclnt *rpc)
{
struct socket *so;
@@ -833,8 +580,6 @@ int rpcclnt_umount(struct rpcclnt *rpc)
* Get port number for MOUNTD.
*/
memset(&sdata, 0, sizeof(struct rpc_call_pmap));
memset(&rdata, 0, sizeof(struct rpc_reply_pmap));
sa->sin_port = htons(PMAPPORT);
error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
@@ -869,9 +614,6 @@ int rpcclnt_umount(struct rpcclnt *rpc)
/* Do RPC to umountd. */
memset(&mountd, 0, sizeof(struct rpc_call_mount));
memset(&mdata, 0, sizeof(struct rpc_reply_mount));
strncpy(mountd.mount.rpath, rpc->rc_path, 92);
mountd.mount.len = txdr_unsigned(sizeof(mountd.mount.rpath));