When reading more then one file via nfs and in the mount/unmountall process
occurs a time out the boot process will be aborted, although eventually the
respons from the NFS server arrives.

This patch does not increment the rpc_id for the communication with the server
when we resend a command timed out previously.
Apart if we receive responses from the server with an old RPC ID (smaller then
in the u-boot state machine) we don't interpret that as an error but just drop
the message and wait for the response corresponding to the last message sent.

Signed-off-by: Matthias Brugger <matthias....@gmail.com>
---
 net/nfs.c |  107 ++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 70 insertions(+), 37 deletions(-)

diff --git a/net/nfs.c b/net/nfs.c
index 7f2393f..756d4d3 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -37,8 +37,11 @@
 # define NFS_TIMEOUT CONFIG_NFS_TIMEOUT
 #endif
 
+#define NFS_RPC_ERR    1
+#define NFS_RPC_DROP   124
+
 static int fs_mounted;
-static unsigned long rpc_id;
+static unsigned long rpc_id = 1;
 static int nfs_offset = -1;
 static int nfs_len;
 
@@ -179,7 +182,7 @@ rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int 
datalen)
        int pktlen;
        int sport;
 
-       id = ++rpc_id;
+       id = rpc_id;
        pkt.u.call.id = htonl(id);
        pkt.u.call.type = htonl(MSG_CALL);
        pkt.u.call.rpcvers = htonl(2);  /* use RPC version 2 */
@@ -357,10 +360,13 @@ RPC request dispatcher
 **************************************************************************/
 
 static void
-NfsSend(void)
+NfsSend(uint8_t resend)
 {
        debug("%s\n", __func__);
 
+       if (resend == 0)
+               rpc_id++;
+
        switch (NfsState) {
        case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
                rpc_lookup_req(PROG_MOUNT, 1);
@@ -399,8 +405,10 @@ rpc_lookup_reply(int prog, uchar *pkt, unsigned len)
 
        debug("%s\n", __func__);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -428,8 +436,10 @@ nfs_mount_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -452,13 +462,15 @@ nfs_umountall_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
            rpc_pkt.u.reply.astatus)
-               return -1;
+               return -NFS_RPC_ERR;
 
        fs_mounted = 0;
        memset(dirfh, 0, sizeof(dirfh));
@@ -475,14 +487,16 @@ nfs_lookup_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
            rpc_pkt.u.reply.astatus  ||
            rpc_pkt.u.reply.data[0])
-               return -1;
+               return -NFS_RPC_ERR;
 
        memcpy(filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
 
@@ -499,14 +513,16 @@ nfs_readlink_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
            rpc_pkt.u.reply.astatus  ||
            rpc_pkt.u.reply.data[0])
-               return -1;
+               return -NFS_RPC_ERR;
 
        rlen = ntohl(rpc_pkt.u.reply.data[1]); /* new path length */
 
@@ -534,8 +550,10 @@ nfs_read_reply(uchar *pkt, unsigned len)
 
        memcpy((uchar *)&rpc_pkt, pkt, sizeof(rpc_pkt.u.reply));
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -575,7 +593,7 @@ NfsTimeout(void)
        } else {
                puts("T ");
                NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
-               NfsSend();
+               NfsSend(1);
        }
 }
 
@@ -583,6 +601,7 @@ static void
 NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
 {
        int rlen;
+       int reply;
 
        debug("%s\n", __func__);
 
@@ -591,31 +610,39 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, 
unsigned src, unsigned len)
 
        switch (NfsState) {
        case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
-               rpc_lookup_reply(PROG_MOUNT, pkt, len);
+               if (rpc_lookup_reply(PROG_MOUNT, pkt, len) == -NFS_RPC_DROP)
+                       break;
                NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ;
-               NfsSend();
+               NfsSend(0);
                break;
 
        case STATE_PRCLOOKUP_PROG_NFS_REQ:
-               rpc_lookup_reply(PROG_NFS, pkt, len);
+               if (rpc_lookup_reply(PROG_NFS, pkt, len) == -NFS_RPC_DROP)
+                       break;
                NfsState = STATE_MOUNT_REQ;
-               NfsSend();
+               NfsSend(0);
                break;
 
        case STATE_MOUNT_REQ:
-               if (nfs_mount_reply(pkt, len)) {
+               reply = nfs_mount_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: Cannot mount\n");
                        /* just to be sure... */
                        NfsState = STATE_UMOUNT_REQ;
-                       NfsSend();
+                       NfsSend(0);
                } else {
                        NfsState = STATE_LOOKUP_REQ;
-                       NfsSend();
+                       NfsSend(0);
                }
                break;
 
        case STATE_UMOUNT_REQ:
-               if (nfs_umountall_reply(pkt, len)) {
+               reply = nfs_umountall_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: Cannot umount\n");
                        net_set_state(NETLOOP_FAIL);
                } else {
@@ -625,30 +652,36 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, 
unsigned src, unsigned len)
                break;
 
        case STATE_LOOKUP_REQ:
-               if (nfs_lookup_reply(pkt, len)) {
+               reply = nfs_lookup_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: File lookup fail\n");
                        NfsState = STATE_UMOUNT_REQ;
-                       NfsSend();
+                       NfsSend(0);
                } else {
                        NfsState = STATE_READ_REQ;
                        nfs_offset = 0;
                        nfs_len = NFS_READ_SIZE;
-                       NfsSend();
+                       NfsSend(0);
                }
                break;
 
        case STATE_READLINK_REQ:
-               if (nfs_readlink_reply(pkt, len)) {
+               reply = nfs_readlink_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: Symlink fail\n");
                        NfsState = STATE_UMOUNT_REQ;
-                       NfsSend();
+                       NfsSend(0);
                } else {
                        debug("Symlink --> %s\n", nfs_path);
                        nfs_filename = basename(nfs_path);
                        nfs_path     = dirname(nfs_path);
 
                        NfsState = STATE_MOUNT_REQ;
-                       NfsSend();
+                       NfsSend(0);
                }
                break;
 
@@ -657,16 +690,16 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, 
unsigned src, unsigned len)
                NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
                if (rlen > 0) {
                        nfs_offset += rlen;
-                       NfsSend();
+                       NfsSend(0);
                } else if ((rlen == -NFSERR_ISDIR) || (rlen == -NFSERR_INVAL)) {
                        /* symbolic link */
                        NfsState = STATE_READLINK_REQ;
-                       NfsSend();
+                       NfsSend(0);
                } else {
                        if (!rlen)
                                nfs_download_state = NETLOOP_SUCCESS;
                        NfsState = STATE_UMOUNT_REQ;
-                       NfsSend();
+                       NfsSend(0);
                }
                break;
        }
@@ -751,5 +784,5 @@ NfsStart(void)
        /* zero out server ether in case the server ip has changed */
        memset(NetServerEther, 0, 6);
 
-       NfsSend();
+       NfsSend(0);
 }
-- 
1.7.9.5

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to