[PATCH 6/8] nfs: queue received packets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



It may happen that we receive more than one RPC packet before we come
along to check the result. Instead of handling just a single received
packet and possibly overwriting the last one queue the received RPC
packets.

Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
---
 fs/nfs.c | 52 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 29 insertions(+), 23 deletions(-)

diff --git a/fs/nfs.c b/fs/nfs.c
index b070ca79d5..26ff354c37 100644
--- a/fs/nfs.c
+++ b/fs/nfs.c
@@ -131,6 +131,7 @@ struct nfs_fh {
 };
 
 struct packet {
+	struct list_head list;
 	int len;
 	char data[];
 };
@@ -145,7 +146,7 @@ struct nfs_priv {
 	unsigned manual_nfs_port:1;
 	uint32_t rpc_id;
 	struct nfs_fh rootfh;
-	struct packet *nfs_packet;
+	struct list_head packets;
 };
 
 struct file_priv {
@@ -175,10 +176,6 @@ static void nfs_set_fh(struct inode *inode, struct nfs_fh *fh)
 
 static uint64_t nfs_timer_start;
 
-static int nfs_state;
-#define STATE_DONE			1
-#define STATE_START			2
-
 /*
  * common types used in more than one request:
  *
@@ -384,13 +381,14 @@ static int rpc_check_reply(struct packet *pkt, int rpc_prog,
 	*nfserr = ntoh32(net_read_uint32(data));
 	*nfserr = -*nfserr;
 
-	debug("%s: state: %d, err %d\n", __func__, nfs_state, *nfserr);
+	debug("%s: err %d\n", __func__, *nfserr);
 
 	return 0;
 }
 
 static void nfs_free_packet(struct packet *packet)
 {
+	list_del(&packet->list);
 	free(packet);
 }
 
@@ -406,6 +404,7 @@ static struct packet *rpc_req(struct nfs_priv *npriv, int rpc_prog,
 	unsigned char *payload = net_udp_get_payload(npriv->con);
 	int nfserr;
 	int tries = 0;
+	struct packet *packet;
 
 	npriv->rpc_id++;
 
@@ -451,16 +450,11 @@ again:
 	nfs_timer_start = get_time_ns();
 
 	while (1) {
-		nfs_state = STATE_START;
-
 		if (ctrlc())
 			return ERR_PTR(-EINTR);
 
 		net_poll();
 
-		if (nfs_state != STATE_DONE)
-			continue;
-
 		if (is_timeout(nfs_timer_start, NFS_TIMEOUT)) {
 			tries++;
 			if (tries == NFS_MAX_RESEND)
@@ -468,19 +462,28 @@ again:
 			goto again;
 		}
 
-		ret = rpc_check_reply(npriv->nfs_packet, rpc_prog,
+		if (list_empty(&npriv->packets))
+			continue;
+
+		packet = list_first_entry(&npriv->packets, struct packet, list);
+
+		ret = rpc_check_reply(packet, rpc_prog,
 				      npriv->rpc_id, &nfserr);
-		if (!ret) {
+		if (ret == -EAGAIN) {
+			nfs_free_packet(packet);
+			continue;
+		} else if (ret) {
+			nfs_free_packet(packet);
+			return ERR_PTR(ret);
+		} else {
 			if (rpc_prog == PROG_NFS && nfserr) {
-				nfs_free_packet(npriv->nfs_packet);
+				nfs_free_packet(packet);
 				return ERR_PTR(nfserr);
 			} else {
-				return npriv->nfs_packet;
+				return packet;
 			}
 		}
 	}
-
-	return npriv->nfs_packet;
 }
 
 /*
@@ -954,16 +957,17 @@ static int nfs_read_req(struct file_priv *priv, uint64_t offset,
 	return 0;
 }
 
-static void nfs_handler(void *ctx, char *packet, unsigned len)
+static void nfs_handler(void *ctx, char *p, unsigned len)
 {
-	char *pkt = net_eth_to_udp_payload(packet);
+	char *pkt = net_eth_to_udp_payload(p);
 	struct nfs_priv *npriv = ctx;
+	struct packet *packet;
 
-	nfs_state = STATE_DONE;
+	packet = xmalloc(sizeof(*packet) + len);
+	memcpy(packet->data, pkt, len);
+	packet->len = len;
 
-	npriv->nfs_packet = xmalloc(sizeof(*npriv->nfs_packet) + len);
-	memcpy(npriv->nfs_packet->data, pkt, len);
-	npriv->nfs_packet->len = len;
+	list_add_tail(&packet->list, &npriv->packets);
 }
 
 static int nfs_truncate(struct device_d *dev, FILE *f, loff_t size)
@@ -1324,6 +1328,8 @@ static int nfs_probe(struct device_d *dev)
 
 	dev->priv = npriv;
 
+	INIT_LIST_HEAD(&npriv->packets);
+
 	debug("nfs: mount: %s\n", fsdev->backingstore);
 
 	path = strchr(tmp, ':');
-- 
2.26.0.rc2


_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux