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

Configure Feed

Select the types of activity you want to include in your feed.

tcp: update window_clamp when SO_RCVBUF is set

Commit under Fixes moved recomputing the window clamp to
tcp_measure_rcv_mss() (when scaling_ratio changes).
I suspect it missed the fact that we don't recompute the clamp
when rcvbuf is set. Until scaling_ratio changes we are
stuck with the old window clamp which may be based on
the small initial buffer. scaling_ratio may never change.

Inspired by Eric's recent commit d1361840f8c5 ("tcp: fix
SO_RCVLOWAT and RCVBUF autotuning") plumb the user action
thru to TCP and have it update the clamp.

A smaller fix would be to just have tcp_rcvbuf_grow()
adjust the clamp even if SOCK_RCVBUF_LOCK is set.
But IIUC this is what we were trying to get away from
in the first place.

Fixes: a2cbb1603943 ("tcp: Update window clamping condition")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Eric Dumazet <edumaze@google.com>
Link: https://patch.msgid.link/20260408001438.129165-1-kuba@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Jakub Kicinski and committed by
Paolo Abeni
b0254613 c7211b6e

+18
+1
include/linux/net.h
··· 223 223 int (*sendmsg_locked)(struct sock *sk, struct msghdr *msg, 224 224 size_t size); 225 225 int (*set_rcvlowat)(struct sock *sk, int val); 226 + void (*set_rcvbuf)(struct sock *sk, int val); 226 227 }; 227 228 228 229 #define DECLARE_SOCKADDR(type, dst, src) \
+1
include/net/tcp.h
··· 516 516 int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, 517 517 int flags); 518 518 int tcp_set_rcvlowat(struct sock *sk, int val); 519 + void tcp_set_rcvbuf(struct sock *sk, int val); 519 520 int tcp_set_window_clamp(struct sock *sk, int val); 520 521 521 522 static inline void
+9
net/core/sock.c
··· 966 966 967 967 static void __sock_set_rcvbuf(struct sock *sk, int val) 968 968 { 969 + struct socket *sock = sk->sk_socket; 970 + 969 971 /* Ensure val * 2 fits into an int, to prevent max_t() from treating it 970 972 * as a negative value. 971 973 */ ··· 985 983 * we actually used in getsockopt is the most desirable behavior. 986 984 */ 987 985 WRITE_ONCE(sk->sk_rcvbuf, max_t(int, val * 2, SOCK_MIN_RCVBUF)); 986 + 987 + if (sock) { 988 + const struct proto_ops *ops = READ_ONCE(sock->ops); 989 + 990 + if (ops->set_rcvbuf) 991 + ops->set_rcvbuf(sk, sk->sk_rcvbuf); 992 + } 988 993 } 989 994 990 995 void sock_set_rcvbuf(struct sock *sk, int val)
+1
net/ipv4/af_inet.c
··· 1091 1091 .compat_ioctl = inet_compat_ioctl, 1092 1092 #endif 1093 1093 .set_rcvlowat = tcp_set_rcvlowat, 1094 + .set_rcvbuf = tcp_set_rcvbuf, 1094 1095 }; 1095 1096 EXPORT_SYMBOL(inet_stream_ops); 1096 1097
+5
net/ipv4/tcp.c
··· 1858 1858 return 0; 1859 1859 } 1860 1860 1861 + void tcp_set_rcvbuf(struct sock *sk, int val) 1862 + { 1863 + tcp_set_window_clamp(sk, tcp_win_from_space(sk, val)); 1864 + } 1865 + 1861 1866 #ifdef CONFIG_MMU 1862 1867 static const struct vm_operations_struct tcp_vm_ops = { 1863 1868 };
+1
net/ipv6/af_inet6.c
··· 690 690 .compat_ioctl = inet6_compat_ioctl, 691 691 #endif 692 692 .set_rcvlowat = tcp_set_rcvlowat, 693 + .set_rcvbuf = tcp_set_rcvbuf, 693 694 }; 694 695 EXPORT_SYMBOL_GPL(inet6_stream_ops); 695 696