[U-Boot] [PATCH] net: nfs: Fixing error when mounting with time outs
Matthias Brugger
matthias.bgg at gmail.com
Thu Dec 6 11:11:50 CET 2012
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.bgg at 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
More information about the U-Boot
mailing list