o tcp: convert struct tcp_bind_bucket to hlist

parent b3e3e604
...@@ -84,16 +84,27 @@ struct tcp_ehash_bucket { ...@@ -84,16 +84,27 @@ struct tcp_ehash_bucket {
struct tcp_bind_bucket { struct tcp_bind_bucket {
unsigned short port; unsigned short port;
signed short fastreuse; signed short fastreuse;
struct tcp_bind_bucket *next; struct hlist_node node;
struct tcp_bind_bucket **pprev;
struct hlist_head owners; struct hlist_head owners;
}; };
#define tb_for_each(tb, node, head) hlist_for_each_entry(tb, node, head, node)
struct tcp_bind_hashbucket { struct tcp_bind_hashbucket {
spinlock_t lock; spinlock_t lock;
struct tcp_bind_bucket *chain; struct hlist_head chain;
}; };
static inline struct tcp_bind_bucket *__tb_head(struct tcp_bind_hashbucket *head)
{
return hlist_entry(head->chain.first, struct tcp_bind_bucket, node);
}
static inline struct tcp_bind_bucket *tb_head(struct tcp_bind_hashbucket *head)
{
return hlist_empty(&head->chain) ? NULL : __tb_head(head);
}
extern struct tcp_hashinfo { extern struct tcp_hashinfo {
/* This is for sockets with full identity only. Sockets here will /* This is for sockets with full identity only. Sockets here will
* always be without wildcards and will have the following invariant: * always be without wildcards and will have the following invariant:
......
...@@ -2641,7 +2641,7 @@ void __init tcp_init(void) ...@@ -2641,7 +2641,7 @@ void __init tcp_init(void)
panic("Failed to allocate TCP bind hash table\n"); panic("Failed to allocate TCP bind hash table\n");
for (i = 0; i < tcp_bhash_size; i++) { for (i = 0; i < tcp_bhash_size; i++) {
tcp_bhash[i].lock = SPIN_LOCK_UNLOCKED; tcp_bhash[i].lock = SPIN_LOCK_UNLOCKED;
tcp_bhash[i].chain = NULL; INIT_HLIST_HEAD(&tcp_bhash[i].chain);
} }
/* Try to be a bit smarter and adjust defaults depending /* Try to be a bit smarter and adjust defaults depending
......
...@@ -134,10 +134,7 @@ struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head, ...@@ -134,10 +134,7 @@ struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
tb->port = snum; tb->port = snum;
tb->fastreuse = 0; tb->fastreuse = 0;
INIT_HLIST_HEAD(&tb->owners); INIT_HLIST_HEAD(&tb->owners);
if ((tb->next = head->chain) != NULL) hlist_add_head(&tb->node, &head->chain);
tb->next->pprev = &tb->next;
head->chain = tb;
tb->pprev = &head->chain;
} }
return tb; return tb;
} }
...@@ -146,9 +143,7 @@ struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head, ...@@ -146,9 +143,7 @@ struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
void tcp_bucket_destroy(struct tcp_bind_bucket *tb) void tcp_bucket_destroy(struct tcp_bind_bucket *tb)
{ {
if (hlist_empty(&tb->owners)) { if (hlist_empty(&tb->owners)) {
if (tb->next) __hlist_del(&tb->node);
tb->next->pprev = tb->pprev;
*(tb->pprev) = tb->next;
kmem_cache_free(tcp_bucket_cachep, tb); kmem_cache_free(tcp_bucket_cachep, tb);
} }
} }
...@@ -211,6 +206,7 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) ...@@ -211,6 +206,7 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
static int tcp_v4_get_port(struct sock *sk, unsigned short snum) static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
{ {
struct tcp_bind_hashbucket *head; struct tcp_bind_hashbucket *head;
struct hlist_node *node;
struct tcp_bind_bucket *tb; struct tcp_bind_bucket *tb;
int ret; int ret;
...@@ -229,7 +225,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -229,7 +225,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
rover = low; rover = low;
head = &tcp_bhash[tcp_bhashfn(rover)]; head = &tcp_bhash[tcp_bhashfn(rover)];
spin_lock(&head->lock); spin_lock(&head->lock);
for (tb = head->chain; tb; tb = tb->next) tb_for_each(tb, node, &head->chain)
if (tb->port == rover) if (tb->port == rover)
goto next; goto next;
break; break;
...@@ -248,15 +244,17 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -248,15 +244,17 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
* non-NULL and we hold it's mutex. * non-NULL and we hold it's mutex.
*/ */
snum = rover; snum = rover;
tb = NULL;
} else { } else {
head = &tcp_bhash[tcp_bhashfn(snum)]; head = &tcp_bhash[tcp_bhashfn(snum)];
spin_lock(&head->lock); spin_lock(&head->lock);
for (tb = head->chain; tb; tb = tb->next) tb_for_each(tb, node, &head->chain)
if (tb->port == snum) if (tb->port == snum)
break; goto tb_found;
} }
if (tb && !hlist_empty(&tb->owners)) { tb = NULL;
goto tb_not_found;
tb_found:
if (!hlist_empty(&tb->owners)) {
if (sk->sk_reuse > 1) if (sk->sk_reuse > 1)
goto success; goto success;
if (tb->fastreuse > 0 && if (tb->fastreuse > 0 &&
...@@ -268,6 +266,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -268,6 +266,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
goto fail_unlock; goto fail_unlock;
} }
} }
tb_not_found:
ret = 1; ret = 1;
if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL) if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL)
goto fail_unlock; goto fail_unlock;
...@@ -646,6 +645,7 @@ static int tcp_v4_hash_connect(struct sock *sk) ...@@ -646,6 +645,7 @@ static int tcp_v4_hash_connect(struct sock *sk)
int low = sysctl_local_port_range[0]; int low = sysctl_local_port_range[0];
int high = sysctl_local_port_range[1]; int high = sysctl_local_port_range[1];
int remaining = (high - low) + 1; int remaining = (high - low) + 1;
struct hlist_node *node;
struct tcp_tw_bucket *tw = NULL; struct tcp_tw_bucket *tw = NULL;
local_bh_disable(); local_bh_disable();
...@@ -677,7 +677,7 @@ static int tcp_v4_hash_connect(struct sock *sk) ...@@ -677,7 +677,7 @@ static int tcp_v4_hash_connect(struct sock *sk)
* because the established check is already * because the established check is already
* unique enough. * unique enough.
*/ */
for (tb = head->chain; tb; tb = tb->next) { tb_for_each(tb, node, &head->chain) {
if (tb->port == rover) { if (tb->port == rover) {
BUG_TRAP(!hlist_empty(&tb->owners)); BUG_TRAP(!hlist_empty(&tb->owners));
if (tb->fastreuse >= 0) if (tb->fastreuse >= 0)
......
...@@ -157,6 +157,7 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) ...@@ -157,6 +157,7 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
{ {
struct tcp_bind_hashbucket *head; struct tcp_bind_hashbucket *head;
struct tcp_bind_bucket *tb; struct tcp_bind_bucket *tb;
struct hlist_node *node;
int ret; int ret;
local_bh_disable(); local_bh_disable();
...@@ -173,7 +174,7 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) ...@@ -173,7 +174,7 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
rover = low; rover = low;
head = &tcp_bhash[tcp_bhashfn(rover)]; head = &tcp_bhash[tcp_bhashfn(rover)];
spin_lock(&head->lock); spin_lock(&head->lock);
for (tb = head->chain; tb; tb = tb->next) tb_for_each(tb, node, &head->chain)
if (tb->port == rover) if (tb->port == rover)
goto next; goto next;
break; break;
...@@ -190,14 +191,16 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) ...@@ -190,14 +191,16 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
/* OK, here is the one we will use. */ /* OK, here is the one we will use. */
snum = rover; snum = rover;
tb = NULL;
} else { } else {
head = &tcp_bhash[tcp_bhashfn(snum)]; head = &tcp_bhash[tcp_bhashfn(snum)];
spin_lock(&head->lock); spin_lock(&head->lock);
for (tb = head->chain; tb != NULL; tb = tb->next) tb_for_each(tb, node, &head->chain)
if (tb->port == snum) if (tb->port == snum)
break; goto tb_found;
} }
tb = NULL;
goto tb_not_found;
tb_found:
if (tb && !hlist_empty(&tb->owners)) { if (tb && !hlist_empty(&tb->owners)) {
if (tb->fastreuse > 0 && sk->sk_reuse && if (tb->fastreuse > 0 && sk->sk_reuse &&
sk->sk_state != TCP_LISTEN) { sk->sk_state != TCP_LISTEN) {
...@@ -208,9 +211,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) ...@@ -208,9 +211,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
goto fail_unlock; goto fail_unlock;
} }
} }
tb_not_found:
ret = 1; ret = 1;
if (tb == NULL && if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL)
(tb = tcp_bucket_create(head, snum)) == NULL)
goto fail_unlock; goto fail_unlock;
if (hlist_empty(&tb->owners)) { if (hlist_empty(&tb->owners)) {
if (sk->sk_reuse && sk->sk_state != TCP_LISTEN) if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
...@@ -550,7 +553,7 @@ static int tcp_v6_hash_connect(struct sock *sk) ...@@ -550,7 +553,7 @@ static int tcp_v6_hash_connect(struct sock *sk)
} }
head = &tcp_bhash[tcp_bhashfn(inet_sk(sk)->num)]; head = &tcp_bhash[tcp_bhashfn(inet_sk(sk)->num)];
tb = head->chain; tb = tb_head(head);
spin_lock_bh(&head->lock); spin_lock_bh(&head->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment