]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tcp: add RCU management to inet_bind_bucket
authorEric Dumazet <edumazet@google.com>
Sun, 2 Mar 2025 12:42:36 +0000 (12:42 +0000)
committerJakub Kicinski <kuba@kernel.org>
Wed, 5 Mar 2025 01:46:26 +0000 (17:46 -0800)
Add RCU protection to inet_bind_bucket structure.

- Add rcu_head field to the structure definition.

- Use kfree_rcu() at destroy time, and remove inet_bind_bucket_destroy()
  first argument.

- Use hlist_del_rcu() and hlist_add_head_rcu() methods.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250302124237.3913746-4-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/inet_hashtables.h
net/ipv4/inet_connection_sock.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_timewait_sock.c

index da818fb0205fed6b4120946bc032e67e046b716f..1061c4f536a6684fff8e73132dd0dcb4cdb3fbe8 100644 (file)
@@ -89,6 +89,7 @@ struct inet_bind_bucket {
        bool                    fast_ipv6_only;
        struct hlist_node       node;
        struct hlist_head       bhash2;
+       struct rcu_head         rcu;
 };
 
 struct inet_bind2_bucket {
@@ -226,8 +227,7 @@ struct inet_bind_bucket *
 inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
                        struct inet_bind_hashbucket *head,
                        const unsigned short snum, int l3mdev);
-void inet_bind_bucket_destroy(struct kmem_cache *cachep,
-                             struct inet_bind_bucket *tb);
+void inet_bind_bucket_destroy(struct inet_bind_bucket *tb);
 
 bool inet_bind_bucket_match(const struct inet_bind_bucket *tb,
                            const struct net *net, unsigned short port,
index b4e514da22b64f02cbd9f6c10698db359055e0cc..e93c660340770a76446f97617ba23af32dc136fb 100644 (file)
@@ -598,7 +598,7 @@ fail_unlock:
                if (bhash2_created)
                        inet_bind2_bucket_destroy(hinfo->bind2_bucket_cachep, tb2);
                if (bhash_created)
-                       inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb);
+                       inet_bind_bucket_destroy(tb);
        }
        if (head2_lock_acquired)
                spin_unlock(&head2->lock);
index 46d39aa2199ec3a405b50e8e85130e990d2c26b7..b737e13f8459c53428980221355344327c4bc8dd 100644 (file)
@@ -76,7 +76,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
                tb->fastreuse = 0;
                tb->fastreuseport = 0;
                INIT_HLIST_HEAD(&tb->bhash2);
-               hlist_add_head(&tb->node, &head->chain);
+               hlist_add_head_rcu(&tb->node, &head->chain);
        }
        return tb;
 }
@@ -84,11 +84,11 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
 /*
  * Caller must hold hashbucket lock for this tb with local BH disabled
  */
-void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket *tb)
+void inet_bind_bucket_destroy(struct inet_bind_bucket *tb)
 {
        if (hlist_empty(&tb->bhash2)) {
-               __hlist_del(&tb->node);
-               kmem_cache_free(cachep, tb);
+               hlist_del_rcu(&tb->node);
+               kfree_rcu(tb, rcu);
        }
 }
 
@@ -201,7 +201,7 @@ static void __inet_put_port(struct sock *sk)
        }
        spin_unlock(&head2->lock);
 
-       inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
+       inet_bind_bucket_destroy(tb);
        spin_unlock(&head->lock);
 }
 
@@ -285,7 +285,7 @@ bhash2_find:
 
 error:
        if (created_inet_bind_bucket)
-               inet_bind_bucket_destroy(table->bind_bucket_cachep, tb);
+               inet_bind_bucket_destroy(tb);
        spin_unlock(&head2->lock);
        spin_unlock(&head->lock);
        return -ENOMEM;
@@ -1162,7 +1162,7 @@ error:
 
        spin_unlock(&head2->lock);
        if (tb_created)
-               inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb);
+               inet_bind_bucket_destroy(tb);
        spin_unlock(&head->lock);
 
        if (tw)
index 337390ba85b4082701f78f1a0913ba47c1741378..aded4bf1bc16d9f1d9fd80d60f41027dd53f38eb 100644 (file)
@@ -39,7 +39,7 @@ void inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
        tw->tw_tb = NULL;
        tw->tw_tb2 = NULL;
        inet_bind2_bucket_destroy(hashinfo->bind2_bucket_cachep, tb2);
-       inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
+       inet_bind_bucket_destroy(tb);
 
        __sock_put((struct sock *)tw);
 }