mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									25c07e2c5e
								
							
						
					
					
						commit
						9652dc2eb9
					
				
					 2 changed files with 7 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -863,7 +863,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 | 
			
		|||
	s_num = num = cb->args[2];
 | 
			
		||||
 | 
			
		||||
	if (cb->args[0] == 0) {
 | 
			
		||||
		if (!(idiag_states & TCPF_LISTEN))
 | 
			
		||||
		if (!(idiag_states & TCPF_LISTEN) || r->id.idiag_dport)
 | 
			
		||||
			goto skip_listen_ht;
 | 
			
		||||
 | 
			
		||||
		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,
 | 
			
		|||
 | 
			
		||||
			num = 0;
 | 
			
		||||
			ilb = &hashinfo->listening_hash[i];
 | 
			
		||||
			spin_lock_bh(&ilb->lock);
 | 
			
		||||
			spin_lock(&ilb->lock);
 | 
			
		||||
			sk_for_each(sk, &ilb->head) {
 | 
			
		||||
				struct inet_sock *inet = inet_sk(sk);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -892,26 +892,18 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 | 
			
		|||
				    r->id.idiag_sport)
 | 
			
		||||
					goto next_listen;
 | 
			
		||||
 | 
			
		||||
				if (r->id.idiag_dport ||
 | 
			
		||||
				    cb->args[3] > 0)
 | 
			
		||||
					goto next_listen;
 | 
			
		||||
 | 
			
		||||
				if (inet_csk_diag_dump(sk, skb, cb, r,
 | 
			
		||||
						       bc, net_admin) < 0) {
 | 
			
		||||
					spin_unlock_bh(&ilb->lock);
 | 
			
		||||
					spin_unlock(&ilb->lock);
 | 
			
		||||
					goto done;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
next_listen:
 | 
			
		||||
				cb->args[3] = 0;
 | 
			
		||||
				cb->args[4] = 0;
 | 
			
		||||
				++num;
 | 
			
		||||
			}
 | 
			
		||||
			spin_unlock_bh(&ilb->lock);
 | 
			
		||||
			spin_unlock(&ilb->lock);
 | 
			
		||||
 | 
			
		||||
			s_num = 0;
 | 
			
		||||
			cb->args[3] = 0;
 | 
			
		||||
			cb->args[4] = 0;
 | 
			
		||||
		}
 | 
			
		||||
skip_listen_ht:
 | 
			
		||||
		cb->args[0] = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1893,7 +1893,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
 | 
			
		|||
	if (!sk) {
 | 
			
		||||
get_head:
 | 
			
		||||
		ilb = &tcp_hashinfo.listening_hash[st->bucket];
 | 
			
		||||
		spin_lock_bh(&ilb->lock);
 | 
			
		||||
		spin_lock(&ilb->lock);
 | 
			
		||||
		sk = sk_head(&ilb->head);
 | 
			
		||||
		st->offset = 0;
 | 
			
		||||
		goto get_sk;
 | 
			
		||||
| 
						 | 
				
			
			@ -1911,7 +1911,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
 | 
			
		|||
			return sk;
 | 
			
		||||
		icsk = inet_csk(sk);
 | 
			
		||||
	}
 | 
			
		||||
	spin_unlock_bh(&ilb->lock);
 | 
			
		||||
	spin_unlock(&ilb->lock);
 | 
			
		||||
	st->offset = 0;
 | 
			
		||||
	if (++st->bucket < INET_LHTABLE_SIZE)
 | 
			
		||||
		goto get_head;
 | 
			
		||||
| 
						 | 
				
			
			@ -2119,7 +2119,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
 | 
			
		|||
	switch (st->state) {
 | 
			
		||||
	case TCP_SEQ_STATE_LISTENING:
 | 
			
		||||
		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;
 | 
			
		||||
	case TCP_SEQ_STATE_ESTABLISHED:
 | 
			
		||||
		if (v)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue