diff options
author | Jakub Kicinski <kuba@kernel.org> | 2022-06-16 20:13:52 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-06-16 20:13:52 -0700 |
commit | 9cbc9911260f24cd3ce2bfb3bcdf4792366a5745 (patch) | |
tree | 4600a657ac1e8977ff706bf398eb27de2dedab7f /net/ax25/af_ax25.c | |
parent | 5dcb50c009c9f8ec1cfca6a81a05c0060a5bbf68 (diff) | |
parent | 48a23ec6ff2b2a5effe8d3ae5f17fc6b7f35df65 (diff) | |
download | linux-9cbc9911260f24cd3ce2bfb3bcdf4792366a5745.tar.bz2 |
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/af_ax25.c')
-rw-r--r-- | net/ax25/af_ax25.c | 33 |
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; } |