tcp: add RCU management to inet_bind_bucket
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>
This commit is contained in:
committed by
Jakub Kicinski
parent
ca79d80b0b
commit
d186f405fd
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user