Re: [PATCH net-next v5 6/6] tls: Flush backlog before waiting for a new record
"Chuck Lever" <[email protected]> Tue, 24 Mar 2026 15:07:00 -0400
| Newsgroups | dev.linux.lists.kernel-tls-handshake,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Mar 24, 2026, at 12:18 PM, Sabrina Dubroca wrote: > 2026-03-24, 08:53:28 -0400, Chuck Lever wrote: >> From: Chuck Lever <[email protected]> >> >> While lock_sock is held, incoming TCP segments land on >> sk->sk_backlog rather than sk->sk_receive_queue. >> tls_rx_rec_wait() inspects only sk_receive_queue, so >> backlog data remains invisible. For non-blocking callers >> (read_sock, and recvmsg or splice_read with MSG_DONTWAIT) >> this causes a spurious -EAGAIN. For blocking callers it >> forces an unnecessary sleep/wakeup cycle. >> >> Flush the backlog inside tls_rx_rec_wait() before checking >> sk_receive_queue so the strparser can parse newly-arrived >> segments immediately. >> >> Fixes: 20ffc7adf53a ("net/tls: missing received data after fast remote close") > > How did you pick that Fixes tag? That commit mentions FIN/connection > closing, which doesn't seem related to the local backlog. 20ffc7adf53a introduced the sk_receive_queue check inside the wait loop (then called tls_wait_data(), later refactored into tls_rx_rec_wait()). When lock_sock is held, incoming TCP will segments land on sk->sk_backlog, not sk->sk_receive_queue. The sk_receive_queue check introduced by 20ffc7adf53a doesn't see backlog data. >> diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c >> index 8fb2f2a93846..84c4ae0330d1 100644 >> --- a/net/tls/tls_sw.c >> +++ b/net/tls/tls_sw.c >> @@ -1372,6 +1372,7 @@ tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock, >> if (ret < 0) >> return ret; >> >> + sk_flush_backlog(sk); > > Do we need to update released when this returns true, like callers of > tls_read_flush_backlog() do? Good catch. v6 will do that. > I also wonder if we'd want to update the > caller's flushed_at to avoid bypassing the "smart checks" in > tls_read_flush_backlog(). The flush in tls_rx_rec_wait() only fires when the loop finds no ready message, which is the cold path. The redundant flush from tls_read_flush_backlog() on the next iteration is wasteful but harmless. I'm not sure the additional complexity would be worth it, but if you believe it will add some value, let me know and I will add it. >> if (!skb_queue_empty(&sk->sk_receive_queue)) { >> /* Defer notification to the exit point; >> * this thread will consume the record > > -- > Sabrina -- Chuck Lever