summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-06-14 23:27:02 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-06-14 23:27:02 +0000
commitcaab3934ab17cdd56e82e09d47eedeaf563f5a81 (patch)
tree19f2e9ddd144b5fad813653dafee1fbb46388362
parent6d538ea469affc6b33254109c3c2b65c24c14e5d (diff)
downloadpx4-nuttx-caab3934ab17cdd56e82e09d47eedeaf563f5a81.tar.gz
px4-nuttx-caab3934ab17cdd56e82e09d47eedeaf563f5a81.tar.bz2
px4-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.c3
-rw-r--r--nuttx/fs/nfs/nfs_socket.c17
-rw-r--r--nuttx/fs/nfs/rpc.h1
-rw-r--r--nuttx/fs/nfs/rpc_clnt.c182
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)
{