tcp: flush DMA queue before sk_wait_data if rcv_wnd is zero
If recv() syscall is called for a TCP socket so that - IOAT DMA is used - MSG_WAITALL flag is used - requested length is bigger than sk_rcvbuf - enough data has already arrived to bring rcv_wnd to zero then when tcp_recvmsg() gets to calling sk_wait_data(), receive window can be still zero while sk_async_wait_queue exhausts enough space to keep it zero. As this queue isn't cleaned until the tcp_service_net_dma() call, sk_wait_data() cannot receive any data and blocks forever. If zero receive window and non-empty sk_async_wait_queue is detected before calling sk_wait_data(), process the queue first. Signed-off-by: Michal Kubecek <mkubecek@suse.cz> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
dbd6b11e15
commit
15c041759b
|
@ -1762,8 +1762,14 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_NET_DMA
|
||||
if (tp->ucopy.dma_chan)
|
||||
dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
|
||||
if (tp->ucopy.dma_chan) {
|
||||
if (tp->rcv_wnd == 0 &&
|
||||
!skb_queue_empty(&sk->sk_async_wait_queue)) {
|
||||
tcp_service_net_dma(sk, true);
|
||||
tcp_cleanup_rbuf(sk, copied);
|
||||
} else
|
||||
dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
|
||||
}
|
||||
#endif
|
||||
if (copied >= target) {
|
||||
/* Do not sleep, just process backlog. */
|
||||
|
|
Loading…
Reference in New Issue