Skip to content

Commit f969dc5

Browse files
Eric Dumazetdavem330
authored andcommitted
tcp: fix SO_RCVLOWAT related hangs under mem pressure
While commit 24adbc1 ("tcp: fix SO_RCVLOWAT hangs with fat skbs") fixed an issue vs too small sk_rcvbuf for given sk_rcvlowat constraint, it missed to address issue caused by memory pressure. 1) If we are under memory pressure and socket receive queue is empty. First incoming packet is allowed to be queued, after commit 76dfa60 ("tcp: allow one skb to be received per socket under memory pressure") But we do not send EPOLLIN yet, in case tcp_data_ready() sees sk_rcvlowat is bigger than skb length. 2) Then, when next packet comes, it is dropped, and we directly call sk->sk_data_ready(). 3) If application is using poll(), tcp_poll() will then use tcp_stream_is_readable() and decide the socket receive queue is not yet filled, so nothing will happen. Even when sender retransmits packets, phases 2) & 3) repeat and flow is effectively frozen, until memory pressure is off. Fix is to consider tcp_under_memory_pressure() to take care of global memory pressure or memcg pressure. Fixes: 24adbc1 ("tcp: fix SO_RCVLOWAT hangs with fat skbs") Signed-off-by: Eric Dumazet <[email protected]> Reported-by: Arjun Roy <[email protected]> Suggested-by: Wei Wang <[email protected]> Reviewed-by: Wei Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5cdaf9d commit f969dc5

File tree

1 file changed

+7
-2
lines changed

1 file changed

+7
-2
lines changed

include/net/tcp.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,8 +1431,13 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied);
14311431
*/
14321432
static inline bool tcp_rmem_pressure(const struct sock *sk)
14331433
{
1434-
int rcvbuf = READ_ONCE(sk->sk_rcvbuf);
1435-
int threshold = rcvbuf - (rcvbuf >> 3);
1434+
int rcvbuf, threshold;
1435+
1436+
if (tcp_under_memory_pressure(sk))
1437+
return true;
1438+
1439+
rcvbuf = READ_ONCE(sk->sk_rcvbuf);
1440+
threshold = rcvbuf - (rcvbuf >> 3);
14361441

14371442
return atomic_read(&sk->sk_rmem_alloc) > threshold;
14381443
}

0 commit comments

Comments
 (0)