Commit 9652dc2e authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

tcp: relax listening_hash operations

softirq handlers use RCU protection to lookup listeners,
and write operations all happen from process context.
We do not need to block BH for dump operations.

Also SYN_RECV since request sockets are stored in the ehash table :

 1) inet_diag_dump_icsk() no longer need to clear
    cb->args[3] and cb->args[4] that were used as cursors while
    iterating the old per listener hash table.

 2) Also factorize a test : No need to scan listening_hash[]
    if r->id.idiag_dport is not zero.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 25c07e2c
...@@ -863,7 +863,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, ...@@ -863,7 +863,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
s_num = num = cb->args[2]; s_num = num = cb->args[2];
if (cb->args[0] == 0) { if (cb->args[0] == 0) {
if (!(idiag_states & TCPF_LISTEN)) if (!(idiag_states & TCPF_LISTEN) || r->id.idiag_dport)
goto skip_listen_ht; goto skip_listen_ht;
for (i = s_i; i < INET_LHTABLE_SIZE; i++) { for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
...@@ -872,7 +872,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, ...@@ -872,7 +872,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
num = 0; num = 0;
ilb = &hashinfo->listening_hash[i]; ilb = &hashinfo->listening_hash[i];
spin_lock_bh(&ilb->lock); spin_lock(&ilb->lock);
sk_for_each(sk, &ilb->head) { sk_for_each(sk, &ilb->head) {
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
...@@ -892,26 +892,18 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, ...@@ -892,26 +892,18 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
r->id.idiag_sport) r->id.idiag_sport)
goto next_listen; goto next_listen;
if (r->id.idiag_dport ||
cb->args[3] > 0)
goto next_listen;
if (inet_csk_diag_dump(sk, skb, cb, r, if (inet_csk_diag_dump(sk, skb, cb, r,
bc, net_admin) < 0) { bc, net_admin) < 0) {
spin_unlock_bh(&ilb->lock); spin_unlock(&ilb->lock);
goto done; goto done;
} }
next_listen: next_listen:
cb->args[3] = 0;
cb->args[4] = 0;
++num; ++num;
} }
spin_unlock_bh(&ilb->lock); spin_unlock(&ilb->lock);
s_num = 0; s_num = 0;
cb->args[3] = 0;
cb->args[4] = 0;
} }
skip_listen_ht: skip_listen_ht:
cb->args[0] = 1; cb->args[0] = 1;
......
...@@ -1893,7 +1893,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -1893,7 +1893,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
if (!sk) { if (!sk) {
get_head: get_head:
ilb = &tcp_hashinfo.listening_hash[st->bucket]; ilb = &tcp_hashinfo.listening_hash[st->bucket];
spin_lock_bh(&ilb->lock); spin_lock(&ilb->lock);
sk = sk_head(&ilb->head); sk = sk_head(&ilb->head);
st->offset = 0; st->offset = 0;
goto get_sk; goto get_sk;
...@@ -1911,7 +1911,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -1911,7 +1911,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
return sk; return sk;
icsk = inet_csk(sk); icsk = inet_csk(sk);
} }
spin_unlock_bh(&ilb->lock); spin_unlock(&ilb->lock);
st->offset = 0; st->offset = 0;
if (++st->bucket < INET_LHTABLE_SIZE) if (++st->bucket < INET_LHTABLE_SIZE)
goto get_head; goto get_head;
...@@ -2119,7 +2119,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v) ...@@ -2119,7 +2119,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
switch (st->state) { switch (st->state) {
case TCP_SEQ_STATE_LISTENING: case TCP_SEQ_STATE_LISTENING:
if (v != SEQ_START_TOKEN) if (v != SEQ_START_TOKEN)
spin_unlock_bh(&tcp_hashinfo.listening_hash[st->bucket].lock); spin_unlock(&tcp_hashinfo.listening_hash[st->bucket].lock);
break; break;
case TCP_SEQ_STATE_ESTABLISHED: case TCP_SEQ_STATE_ESTABLISHED:
if (v) if (v)
......
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