neighbour: Convert seq_file functions to use hlist

Convert seq_file-related neighbour functionality to use neighbour::hash
and the related for_each macro.

Signed-off-by: Gilad Naaman <gnaaman@drivenets.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20241107160444.2913124-4-gnaaman@drivenets.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Gilad Naaman
2024-11-07 16:04:40 +00:00
committed by Jakub Kicinski
parent d7ddee1a52
commit 00df5e1a3f

View File

@@ -3193,43 +3193,53 @@ EXPORT_SYMBOL(neigh_xmit);
#ifdef CONFIG_PROC_FS
static struct neighbour *neigh_get_first(struct seq_file *seq)
static struct neighbour *neigh_get_valid(struct seq_file *seq,
struct neighbour *n,
loff_t *pos)
{
struct neigh_seq_state *state = seq->private;
struct net *net = seq_file_net(seq);
if (!net_eq(dev_net(n->dev), net))
return NULL;
if (state->neigh_sub_iter) {
loff_t fakep = 0;
void *v;
v = state->neigh_sub_iter(state, n, pos ? pos : &fakep);
if (!v)
return NULL;
if (pos)
return v;
}
if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
return n;
if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
return n;
return NULL;
}
static struct neighbour *neigh_get_first(struct seq_file *seq)
{
struct neigh_seq_state *state = seq->private;
struct neigh_hash_table *nht = state->nht;
struct neighbour *n = NULL;
int bucket;
struct neighbour *n, *tmp;
state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
n = rcu_dereference(nht->hash_buckets[bucket]);
while (n) {
if (!net_eq(dev_net(n->dev), net))
goto next;
if (state->neigh_sub_iter) {
loff_t fakep = 0;
void *v;
v = state->neigh_sub_iter(state, n, &fakep);
if (!v)
goto next;
}
if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
break;
if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
break;
next:
n = rcu_dereference(n->next);
while (++state->bucket < (1 << nht->hash_shift)) {
neigh_for_each_in_bucket(n, &nht->hash_heads[state->bucket]) {
tmp = neigh_get_valid(seq, n, NULL);
if (tmp)
return tmp;
}
if (n)
break;
}
state->bucket = bucket;
return n;
return NULL;
}
static struct neighbour *neigh_get_next(struct seq_file *seq,
@@ -3237,46 +3247,28 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
loff_t *pos)
{
struct neigh_seq_state *state = seq->private;
struct net *net = seq_file_net(seq);
struct neigh_hash_table *nht = state->nht;
struct neighbour *tmp;
if (state->neigh_sub_iter) {
void *v = state->neigh_sub_iter(state, n, pos);
if (v)
return n;
}
n = rcu_dereference(n->next);
while (1) {
while (n) {
if (!net_eq(dev_net(n->dev), net))
goto next;
if (state->neigh_sub_iter) {
void *v = state->neigh_sub_iter(state, n, pos);
if (v)
return n;
goto next;
}
if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
break;
if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
break;
next:
n = rcu_dereference(n->next);
hlist_for_each_entry_continue(n, hash) {
tmp = neigh_get_valid(seq, n, pos);
if (tmp) {
n = tmp;
goto out;
}
if (n)
break;
if (++state->bucket >= (1 << nht->hash_shift))
break;
n = rcu_dereference(nht->hash_buckets[state->bucket]);
}
n = neigh_get_first(seq);
out:
if (n && pos)
--(*pos);
return n;
}
@@ -3379,7 +3371,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl
struct neigh_seq_state *state = seq->private;
state->tbl = tbl;
state->bucket = 0;
state->bucket = -1;
state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
rcu_read_lock();