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