aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_minisocks.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_minisocks.c')
-rw-r--r--net/ipv4/tcp_minisocks.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 85830bb92d04..e0a87c238882 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -362,27 +362,35 @@ void tcp_twsk_destructor(struct sock *sk)
362} 362}
363EXPORT_SYMBOL_GPL(tcp_twsk_destructor); 363EXPORT_SYMBOL_GPL(tcp_twsk_destructor);
364 364
365/* Warning : This function is called without sk_listener being locked.
366 * Be sure to read socket fields once, as their value could change under us.
367 */
365void tcp_openreq_init_rwin(struct request_sock *req, 368void tcp_openreq_init_rwin(struct request_sock *req,
366 struct sock *sk, struct dst_entry *dst) 369 const struct sock *sk_listener,
370 const struct dst_entry *dst)
367{ 371{
368 struct inet_request_sock *ireq = inet_rsk(req); 372 struct inet_request_sock *ireq = inet_rsk(req);
369 struct tcp_sock *tp = tcp_sk(sk); 373 const struct tcp_sock *tp = tcp_sk(sk_listener);
370 __u8 rcv_wscale; 374 u16 user_mss = READ_ONCE(tp->rx_opt.user_mss);
375 int full_space = tcp_full_space(sk_listener);
371 int mss = dst_metric_advmss(dst); 376 int mss = dst_metric_advmss(dst);
377 u32 window_clamp;
378 __u8 rcv_wscale;
372 379
373 if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss) 380 if (user_mss && user_mss < mss)
374 mss = tp->rx_opt.user_mss; 381 mss = user_mss;
375 382
383 window_clamp = READ_ONCE(tp->window_clamp);
376 /* Set this up on the first call only */ 384 /* Set this up on the first call only */
377 req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW); 385 req->window_clamp = window_clamp ? : dst_metric(dst, RTAX_WINDOW);
378 386
379 /* limit the window selection if the user enforce a smaller rx buffer */ 387 /* limit the window selection if the user enforce a smaller rx buffer */
380 if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && 388 if (sk_listener->sk_userlocks & SOCK_RCVBUF_LOCK &&
381 (req->window_clamp > tcp_full_space(sk) || req->window_clamp == 0)) 389 (req->window_clamp > full_space || req->window_clamp == 0))
382 req->window_clamp = tcp_full_space(sk); 390 req->window_clamp = full_space;
383 391
384 /* tcp_full_space because it is guaranteed to be the first packet */ 392 /* tcp_full_space because it is guaranteed to be the first packet */
385 tcp_select_initial_window(tcp_full_space(sk), 393 tcp_select_initial_window(full_space,
386 mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0), 394 mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
387 &req->rcv_wnd, 395 &req->rcv_wnd,
388 &req->window_clamp, 396 &req->window_clamp,