tcp: seq_file: Add listening_get_first()
The current listening_get_next() is overloaded by passing NULL to the 2nd arg, like listening_get_next(seq, NULL), to mean get_first(). This patch moves some logic from the listening_get_next() into a new function listening_get_first(). It will be equivalent to the current established_get_first() and established_get_next() setup. get_first() is to find a non empty bucket and return the first sk. get_next() is to find the next sk of the current bucket and then resorts to get_first() if the current bucket is exhausted. The next patch is to move the listener seq_file iteration from listening_hash (port only) to lhash2 (port+addr). Separating out listening_get_first() from listening_get_next() here will make the following lhash2 changes cleaner and easier to follow. Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Eric Dumazet <edumazet@google.com> Acked-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210701200600.1035353-1-kafai@fb.com
This commit is contained in:
parent
62001372c2
commit
b72acf4501
@ -2288,10 +2288,38 @@ static bool seq_sk_match(struct seq_file *seq, const struct sock *sk)
|
||||
net_eq(sock_net(sk), seq_file_net(seq)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get next listener socket follow cur. If cur is NULL, get first socket
|
||||
* starting from bucket given in st->bucket; when st->bucket is zero the
|
||||
* very first socket in the hash table is returned.
|
||||
/* Find a non empty bucket (starting from st->bucket)
|
||||
* and return the first sk from it.
|
||||
*/
|
||||
static void *listening_get_first(struct seq_file *seq)
|
||||
{
|
||||
struct tcp_iter_state *st = seq->private;
|
||||
|
||||
st->offset = 0;
|
||||
for (; st->bucket < INET_LHTABLE_SIZE; st->bucket++) {
|
||||
struct inet_listen_hashbucket *ilb;
|
||||
struct hlist_nulls_node *node;
|
||||
struct sock *sk;
|
||||
|
||||
ilb = &tcp_hashinfo.listening_hash[st->bucket];
|
||||
if (hlist_nulls_empty(&ilb->nulls_head))
|
||||
continue;
|
||||
|
||||
spin_lock(&ilb->lock);
|
||||
sk_nulls_for_each(sk, node, &ilb->nulls_head) {
|
||||
if (seq_sk_match(seq, sk))
|
||||
return sk;
|
||||
}
|
||||
spin_unlock(&ilb->lock);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the next sk of "cur" within the same bucket (i.e. st->bucket).
|
||||
* If "cur" is the last one in the st->bucket,
|
||||
* call listening_get_first() to return the first sk of the next
|
||||
* non empty bucket.
|
||||
*/
|
||||
static void *listening_get_next(struct seq_file *seq, void *cur)
|
||||
{
|
||||
@ -2300,29 +2328,20 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
|
||||
struct hlist_nulls_node *node;
|
||||
struct sock *sk = cur;
|
||||
|
||||
if (!sk) {
|
||||
get_head:
|
||||
ilb = &tcp_hashinfo.listening_hash[st->bucket];
|
||||
spin_lock(&ilb->lock);
|
||||
sk = sk_nulls_head(&ilb->nulls_head);
|
||||
st->offset = 0;
|
||||
goto get_sk;
|
||||
}
|
||||
ilb = &tcp_hashinfo.listening_hash[st->bucket];
|
||||
++st->num;
|
||||
++st->offset;
|
||||
|
||||
sk = sk_nulls_next(sk);
|
||||
get_sk:
|
||||
|
||||
sk_nulls_for_each_from(sk, node) {
|
||||
if (seq_sk_match(seq, sk))
|
||||
return sk;
|
||||
}
|
||||
|
||||
ilb = &tcp_hashinfo.listening_hash[st->bucket];
|
||||
spin_unlock(&ilb->lock);
|
||||
st->offset = 0;
|
||||
if (++st->bucket < INET_LHTABLE_SIZE)
|
||||
goto get_head;
|
||||
return NULL;
|
||||
++st->bucket;
|
||||
return listening_get_first(seq);
|
||||
}
|
||||
|
||||
static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
|
||||
@ -2332,7 +2351,7 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
|
||||
|
||||
st->bucket = 0;
|
||||
st->offset = 0;
|
||||
rc = listening_get_next(seq, NULL);
|
||||
rc = listening_get_first(seq);
|
||||
|
||||
while (rc && *pos) {
|
||||
rc = listening_get_next(seq, rc);
|
||||
@ -2440,7 +2459,7 @@ static void *tcp_seek_last_pos(struct seq_file *seq)
|
||||
if (st->bucket >= INET_LHTABLE_SIZE)
|
||||
break;
|
||||
st->state = TCP_SEQ_STATE_LISTENING;
|
||||
rc = listening_get_next(seq, NULL);
|
||||
rc = listening_get_first(seq);
|
||||
while (offset-- && rc && bucket == st->bucket)
|
||||
rc = listening_get_next(seq, rc);
|
||||
if (rc)
|
||||
|
Loading…
Reference in New Issue
Block a user