summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-03-30 10:16:14 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2020-03-30 11:08:46 +0200
commit5330e7865ed615f9782c26c9d35196ca1a3aa64c (patch)
tree2e004e8bb245f9d0d04e77490d93031887f879f9 /fs
parent5473abac14fdb1ba1cd4599175a1ac17bd5ee3d1 (diff)
downloadbarebox-5330e7865ed615f9782c26c9d35196ca1a3aa64c.tar.gz
barebox-5330e7865ed615f9782c26c9d35196ca1a3aa64c.tar.xz
nfs: queue received packets
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@pengutronix.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs.c52
1 files 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, ':');