summaryrefslogtreecommitdiff
path: root/net/ax25
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-06-16 20:13:52 -0700
committerJakub Kicinski <kuba@kernel.org>2022-06-16 20:13:52 -0700
commit9cbc9911260f24cd3ce2bfb3bcdf4792366a5745 (patch)
tree4600a657ac1e8977ff706bf398eb27de2dedab7f /net/ax25
parent5dcb50c009c9f8ec1cfca6a81a05c0060a5bbf68 (diff)
parent48a23ec6ff2b2a5effe8d3ae5f17fc6b7f35df65 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
No conflicts. Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ax25')
-rw-r--r--net/ax25/af_ax25.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 1a5c0b071aa3..bbac3cb4dc99 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1662,9 +1662,12 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
struct sock *sk = sock->sk;
- struct sk_buff *skb;
+ struct sk_buff *skb, *last;
+ struct sk_buff_head *sk_queue;
int copied;
int err = 0;
+ int off = 0;
+ long timeo;
lock_sock(sk);
/*
@@ -1676,10 +1679,29 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
goto out;
}
- /* Now we can treat all alike */
- skb = skb_recv_datagram(sk, flags, &err);
- if (skb == NULL)
- goto out;
+ /* We need support for non-blocking reads. */
+ sk_queue = &sk->sk_receive_queue;
+ skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off, &err, &last);
+ /* If no packet is available, release_sock(sk) and try again. */
+ if (!skb) {
+ if (err != -EAGAIN)
+ goto out;
+ release_sock(sk);
+ timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+ while (timeo && !__skb_wait_for_more_packets(sk, sk_queue, &err,
+ &timeo, last)) {
+ skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off,
+ &err, &last);
+ if (skb)
+ break;
+
+ if (err != -EAGAIN)
+ goto done;
+ }
+ if (!skb)
+ goto done;
+ lock_sock(sk);
+ }
if (!sk_to_ax25(sk)->pidincl)
skb_pull(skb, 1); /* Remove PID */
@@ -1726,6 +1748,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
out:
release_sock(sk);
+done:
return err;
}