Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: set TCP_SYNCNT locklessly

icsk->icsk_syn_retries can safely be set without locking the socket.

We have to add READ_ONCE() annotations in tcp_fastopen_synack_timer()
and tcp_write_timeout().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Dumazet and committed by
David S. Miller
d44fd4a7 81083076

+12 -12
+6 -9
net/ipv4/tcp.c
··· 3291 3291 if (val < 1 || val > MAX_TCP_SYNCNT) 3292 3292 return -EINVAL; 3293 3293 3294 - lock_sock(sk); 3295 3294 WRITE_ONCE(inet_csk(sk)->icsk_syn_retries, val); 3296 - release_sock(sk); 3297 3295 return 0; 3298 3296 } 3299 3297 EXPORT_SYMBOL(tcp_sock_set_syncnt); ··· 3460 3462 if (copy_from_sockptr(&val, optval, sizeof(val))) 3461 3463 return -EFAULT; 3462 3464 3465 + /* Handle options that can be set without locking the socket. */ 3466 + switch (optname) { 3467 + case TCP_SYNCNT: 3468 + return tcp_sock_set_syncnt(sk, val); 3469 + } 3470 + 3463 3471 sockopt_lock_sock(sk); 3464 3472 3465 3473 switch (optname) { ··· 3573 3569 else 3574 3570 WRITE_ONCE(tp->keepalive_probes, val); 3575 3571 break; 3576 - case TCP_SYNCNT: 3577 - if (val < 1 || val > MAX_TCP_SYNCNT) 3578 - err = -EINVAL; 3579 - else 3580 - WRITE_ONCE(icsk->icsk_syn_retries, val); 3581 - break; 3582 - 3583 3572 case TCP_SAVE_SYN: 3584 3573 /* 0: disable, 1: enable, 2: start from ether_header */ 3585 3574 if (val < 0 || val > 2)
+6 -3
net/ipv4/tcp_timer.c
··· 239 239 if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { 240 240 if (icsk->icsk_retransmits) 241 241 __dst_negative_advice(sk); 242 - retry_until = icsk->icsk_syn_retries ? : 242 + /* Paired with WRITE_ONCE() in tcp_sock_set_syncnt() */ 243 + retry_until = READ_ONCE(icsk->icsk_syn_retries) ? : 243 244 READ_ONCE(net->ipv4.sysctl_tcp_syn_retries); 244 245 245 246 max_retransmits = retry_until; ··· 422 421 423 422 req->rsk_ops->syn_ack_timeout(req); 424 423 425 - /* add one more retry for fastopen */ 426 - max_retries = icsk->icsk_syn_retries ? : 424 + /* Add one more retry for fastopen. 425 + * Paired with WRITE_ONCE() in tcp_sock_set_syncnt() 426 + */ 427 + max_retries = READ_ONCE(icsk->icsk_syn_retries) ? : 427 428 READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_synack_retries) + 1; 428 429 429 430 if (req->num_timeout >= max_retries) {