tcp: set TCP_DEFER_ACCEPT locklessly
authorEric Dumazet <edumazet@google.com>
Fri, 4 Aug 2023 14:46:16 +0000 (14:46 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 6 Aug 2023 07:24:56 +0000 (08:24 +0100)
rskq_defer_accept field can be read/written without
the need of holding the socket lock.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_minisocks.c

index 5c71b4f..4fbc7ff 100644 (file)
@@ -3479,6 +3479,12 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                else
                        WRITE_ONCE(tp->linger2, val * HZ);
                return 0;
+       case TCP_DEFER_ACCEPT:
+               /* Translate value in seconds to number of retransmits */
+               WRITE_ONCE(icsk->icsk_accept_queue.rskq_defer_accept,
+                          secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
+                                          TCP_RTO_MAX / HZ));
+               return 0;
        }
 
        sockopt_lock_sock(sk);
@@ -3584,13 +3590,6 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                        tp->save_syn = val;
                break;
 
-       case TCP_DEFER_ACCEPT:
-               /* Translate value in seconds to number of retransmits */
-               WRITE_ONCE(icsk->icsk_accept_queue.rskq_defer_accept,
-                          secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
-                                          TCP_RTO_MAX / HZ));
-               break;
-
        case TCP_WINDOW_CLAMP:
                err = tcp_set_window_clamp(sk, val);
                break;
index deac708..8e96ebe 100644 (file)
@@ -6324,7 +6324,7 @@ consume:
                if (fastopen_fail)
                        return -1;
                if (sk->sk_write_pending ||
-                   icsk->icsk_accept_queue.rskq_defer_accept ||
+                   READ_ONCE(icsk->icsk_accept_queue.rskq_defer_accept) ||
                    inet_csk_in_pingpong_mode(sk)) {
                        /* Save one ACK. Data will be ready after
                         * several ticks, if write_pending is set.
index ddba3b6..13ee129 100644 (file)
@@ -792,7 +792,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                return sk;
 
        /* While TCP_DEFER_ACCEPT is active, drop bare ACK. */
-       if (req->num_timeout < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+       if (req->num_timeout < READ_ONCE(inet_csk(sk)->icsk_accept_queue.rskq_defer_accept) &&
            TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
                inet_rsk(req)->acked = 1;
                __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP);