diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-06-14 23:27:02 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-06-14 23:27:02 +0000 |
commit | caab3934ab17cdd56e82e09d47eedeaf563f5a81 (patch) | |
tree | 19f2e9ddd144b5fad813653dafee1fbb46388362 | |
parent | 6d538ea469affc6b33254109c3c2b65c24c14e5d (diff) | |
download | nuttx-caab3934ab17cdd56e82e09d47eedeaf563f5a81.tar.gz nuttx-caab3934ab17cdd56e82e09d47eedeaf563f5a81.tar.bz2 nuttx-caab3934ab17cdd56e82e09d47eedeaf563f5a81.zip |
Improve NFS retry logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4845 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | apps/nshlib/nsh_envcmds.c | 3 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_socket.c | 17 | ||||
-rw-r--r-- | nuttx/fs/nfs/rpc.h | 1 | ||||
-rw-r--r-- | nuttx/fs/nfs/rpc_clnt.c | 182 |
4 files changed, 134 insertions, 69 deletions
diff --git a/apps/nshlib/nsh_envcmds.c b/apps/nshlib/nsh_envcmds.c index 7603bf779..07b775517 100644 --- a/apps/nshlib/nsh_envcmds.c +++ b/apps/nshlib/nsh_envcmds.c @@ -109,7 +109,7 @@ static inline char *nsh_getdirpath(FAR struct nsh_vtbl_s *vtbl, char *alloc; int len; - /* Handle the special case where the dirpath is simply */ + /* Handle the special case where the dirpath is simply "/" */ if (strcmp(dirpath, "/") == 0) { @@ -151,6 +151,7 @@ FAR const char *nsh_getcwd(void) return nsh_getwd(g_pwd); } #endif + /**************************************************************************** * Name: nsh_getfullpath ****************************************************************************/ diff --git a/nuttx/fs/nfs/nfs_socket.c b/nuttx/fs/nfs/nfs_socket.c index dd2d45841..b0159372e 100644 --- a/nuttx/fs/nfs/nfs_socket.c +++ b/nuttx/fs/nfs/nfs_socket.c @@ -80,6 +80,10 @@ struct nfsstats nfsstats; * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: nfs_init + ****************************************************************************/ + void nfs_init(void) { nfs_true = txdr_unsigned(TRUE); @@ -89,6 +93,10 @@ void nfs_init(void) rpcclnt_init(); } +/**************************************************************************** + * Name: nfs_connect + ****************************************************************************/ + int nfs_connect(struct nfsmount *nmp) { struct rpcclnt *rpc; @@ -114,13 +122,20 @@ int nfs_connect(struct nfsmount *nmp) rpc->rc_path = nmp->nm_path; rpc->rc_name = &nmp->nm_nam; rpc->rc_sotype = nmp->nm_sotype; + rpc->rc_retry = nmp->nm_retry; nmp->nm_rpcclnt = rpc; return rpcclnt_connect(rpc); } -/* NFS disconnect. Clean up and unlink. */ +/**************************************************************************** + * Name: nfs_disconnect + * + * Description: + * NFS disconnect. Clean up and unlink. + * + ****************************************************************************/ void nfs_disconnect(struct nfsmount *nmp) { diff --git a/nuttx/fs/nfs/rpc.h b/nuttx/fs/nfs/rpc.h index 653802b10..6c3415c81 100644 --- a/nuttx/fs/nfs/rpc.h +++ b/nuttx/fs/nfs/rpc.h @@ -512,6 +512,7 @@ struct rpcclnt uint8_t rc_clntflags; /* For RPCCLNT_* flags */ uint8_t rc_sotype; /* Type of socket */ + uint8_t rc_retry; /* Max retries */ /* These describe the current RPC call */ diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c index c20a04cd9..ed9550f20 100644 --- a/nuttx/fs/nfs/rpc_clnt.c +++ b/nuttx/fs/nfs/rpc_clnt.c @@ -150,10 +150,18 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, * Private Functions ****************************************************************************/ -/* This is the nfs send routine. Returns EINTR if the RPC is terminated, 0 - * otherwise - set RPCCALL_MUSTRESEND if the send fails for any reason - do any - * cleanup required by recoverable socket errors. - */ +/**************************************************************************** + * Name: rpcclnt_send + * + * Description: + * This is the nfs send routine. + * + * Returned Value: + * Returns EINTR if the RPC is terminated, 0 otherwise - set + * RPCCALL_MUSTRESEND if the send fails for any reason - do anycleanup + * required by recoverable socket errors. * + * + ****************************************************************************/ static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, FAR void *call, int reqlen) @@ -190,15 +198,18 @@ static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, return error; } -/* Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all - * done by psock_recvfrom(). For SOCK_STREAM, first get the - * Record Mark to find out how much more there is to get. We must - * lock the socket against other receivers until we have an entire - * rpc request/reply. - */ +/**************************************************************************** + * Name: rpcclnt_receive + * + * Description: + * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all done + * by psock_recvfrom(). + * + ****************************************************************************/ -static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname, - int proc, int program, void *reply, size_t resplen) +static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, + int proc, int program, FAR void *reply, + size_t resplen) { ssize_t nbytes; int error = 0; @@ -219,67 +230,64 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname, return error; } -/* Implement receipt of reply on a socket. We must search through the list of - * received datagrams matching them with outstanding requests using the xid, - * until ours is found. - */ +/**************************************************************************** + * Name: rpcclnt_reply + * + * Description: + * Received the RPC reply on the socket. + * + ****************************************************************************/ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, - void *reply, size_t resplen) + FAR void *reply, size_t resplen) { FAR struct rpc_reply_header *replyheader; uint32_t rxid; int error; - int count; - /* Loop around until we get our own reply */ + /* Get the next RPC reply from the socket */ - for (count = 0; count < 9; count++) + error = rpcclnt_receive(rpc, rpc->rc_name, procid, prog, reply, resplen); + if (error != 0) { - /* Get the next RPC reply off the socket */ - - error = rpcclnt_receive(rpc, rpc->rc_name, procid, prog, reply, resplen); - if (error != 0) - { - fdbg("ERROR: rpcclnt_receive returned: %d\n"); - - /* Ignore non-fatal errors and try again */ + fdbg("ERROR: rpcclnt_receive returned: %d\n"); - if (error != EINTR && error != ERESTART && error != EWOULDBLOCK) - { - fdbg(" Ignoring routing error\n"); - continue; - } + /* If we failed because of a timeout, then try sending the CALL + * message again. + */ - return error; - } + if (error == EAGAIN || error == ETIMEDOUT || error == EINTR) + { + rpc->rc_callflags |= RPCCALL_MUSTRESEND; + } - /* Get the xid and check that it is an RPC replysvr */ + return error; + } - replyheader = (FAR struct rpc_reply_header *)reply; - rxid = replyheader->rp_xid; + /* Get the xid and check that it is an RPC replysvr */ - if (replyheader->rp_direction != rpc_reply) - { - rpc_statistics(rpcinvalid); - continue; - } + replyheader = (FAR struct rpc_reply_header *)reply; + rxid = replyheader->rp_xid; - return OK; + if (replyheader->rp_direction != rpc_reply) + { + rpc_statistics(rpcinvalid); + fdbg("ERROR: Different RPC REPLY returned\n"); + rpc->rc_callflags |= RPCCALL_MUSTRESEND; + error = EAGAIN; + return error; } - /* Here if we tried to receive the response 9 times. If we failed - * because of a timeout, then try sending the CALL message again. - */ - - if (error == EAGAIN || error == ETIMEDOUT) - { - rpc->rc_callflags |= RPCCALL_MUSTRESEND; - } - return error; + return OK; } -/* Get a new (non-zero) xid */ +/**************************************************************************** + * Name: rpcclnt_newxid + * + * Description: + * Get a new (non-zero) xid + * + ****************************************************************************/ static uint32_t rpcclnt_newxid(void) { @@ -307,7 +315,13 @@ static uint32_t rpcclnt_newxid(void) return rpcclnt_xid; } -/* Format the common part of the call header */ +/**************************************************************************** + * Name: rpcclnt_fmtheader + * + * Description: + * Format the common part of the call header + * + ****************************************************************************/ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, uint32_t xid, int prog, int vers, int procid) @@ -336,6 +350,14 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: rpcclnt_init + * + * Description: + * Initialize the RPC client + * + ****************************************************************************/ + void rpcclnt_init(void) { /* RPC constants how about actually using more than one of these! */ @@ -353,9 +375,14 @@ void rpcclnt_init(void) fvdbg("RPC initialized\n"); } -/* Initialize sockets and congestion for a new RPC connection. We do not free - * the sockaddr if error. - */ +/**************************************************************************** + * Name: rpcclnt_connect + * + * Description: + * Initialize sockets for a new RPC connection. We do not free the + * sockaddr if an error occurs. + * + ****************************************************************************/ int rpcclnt_connect(struct rpcclnt *rpc) { @@ -561,6 +588,14 @@ bad: return error; } +/**************************************************************************** + * Name: rpcclnt_disconnect + * + * Description: + * Disconnect from the NFS server. + * + ****************************************************************************/ + void rpcclnt_disconnect(struct rpcclnt *rpc) { struct socket *so; @@ -572,6 +607,14 @@ void rpcclnt_disconnect(struct rpcclnt *rpc) } } +/**************************************************************************** + * Name: rpcclnt_umount + * + * Description: + * Un-mount the NFS file system. + * + ****************************************************************************/ + int rpcclnt_umount(struct rpcclnt *rpc) { struct sockaddr *saddr; @@ -656,15 +699,20 @@ bad: return error; } -/* Code from nfs_request - goes something like this - fill in task struct - - * links task into list - calls nfs_send() for first transmit - calls - * nfs_receive() to get reply - fills in reply (which should be initialized - * prior to calling), which is valid when 0. +/**************************************************************************** + * Name: rpcclnt_request * - * Note that reply->result_* are invalid unless reply->type == - * RPC_MSGACCEPTED and reply->status == RPC_SUCCESS and that reply->verf_* - * are invalid unless reply->type == RPC_MSGACCEPTED - */ + * Description: + * Perform the RPC reqquest. Logic formats the RPC CALL message and calls + * rpcclnt_send to send the RPC CALL message. It then calls rpcclnt_reply() + * to get the response. It may attempt to re-send the CALL message on + * certain errors. + * + * On successful receipt, it verifies the RPC level of the returned values. + * (There may still be be NFS layer errors that will be deted by calling + * logic). + * + ****************************************************************************/ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, int version, FAR void *request, size_t reqlen, @@ -724,7 +772,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, retries++; } - while ((rpc->rc_callflags & RPCCALL_MUSTRESEND) != 0 && retries <= RPC_MAXREXMIT); + while ((rpc->rc_callflags & RPCCALL_MUSTRESEND) != 0 && retries <= rpc->rc_retry); if (error != OK) { |