Re: [PATCH net 1/2] tcp: Fix fastreuse cache initialization on first bind
From: Eric Dumazet
Date: Sun Oct 25 2026 - 07:07:14 EST
Le dim. 25 oct. 2026 à 10:01, Zhewei Yuan <yzwlhm@xxxxxxxxx> a écrit :
>
> inet_csk_update_fastreuse() initializes the reuse caches only when
> tb->bhash2 is empty. Both inet_csk_get_port() and __inet_inherit_port()
> link tb2 before calling it, so this condition is never met.
>
> Fresh buckets therefore miss fastreuse=1 for SO_REUSEADDR, forcing
> repeated binds to scan existing owners. SO_REUSEPORT starts in STRICT
> instead of ANY, causing repeated fast-path misses with alternating
> addresses.
>
> Initialize the caches when tb2 is the sole entry in tb->bhash2 and has
> no owners. Both checks prevent reinitializing an already-used bucket.
>
> On historical net f4377bf85887, 16000 SO_REUSEADDR binds to one IPv4
> address/port take 4256.956 ms before and 20.004 ms after the fix in a
> one-vCPU KVM guest (bind-only means of 3 boots x 3 rounds).
>
> Found by manual inspection and GDB tracing. Codex assisted with
> analysis, validation and wording; test/benchmark assistance is
> described in the cover letter.
>
> Fixes: 8002d44fe84d ("tcp: Check hlist_empty(&tb->bhash2) instead of hlist_empty(&tb->owners).")
> Signed-off-by: Zhewei Yuan <yzwlhm@xxxxxxxxx>
>
> ---
> net/ipv4/inet_connection_sock.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> index 8151c638a24..93b306d91b6 100644
> --- a/net/ipv4/inet_connection_sock.c
> +++ b/net/ipv4/inet_connection_sock.c
> @@ -446,7 +446,8 @@ void inet_csk_update_fastreuse(const struct sock *sk,
> {
> bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
>
> - if (hlist_empty(&tb->bhash2)) {
> + if (hlist_is_singular_node(&tb2->bhash_node, &tb->bhash2) &&
> + hlist_empty(&tb2->owners)) {
> tb->fastreuse = reuse;
> if (sk->sk_reuseport) {
> tb->fastreuseport = FASTREUSEPORT_ANY;
> --
> 2.52.0
>
Indeed, inet_bind2_bucket_init() adds tb2 to tb->bhash2, so the
first-bind branch has been dead since 8002d44fe84d.
Since timewait sockets are also linked on tb2->owners, this is
equivalent to the old hlist_empty(&tb->owners) test.
Reviewed-by: Eric Dumazet <edumazet@edumazet@xxxxxxxxxx>
Please send this patch alone (no cover letter). Patch 2 is not net
material, I doubt we want it
(see my separate feedback on it)