[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241015232529.67605-1-kuniyu@amazon.com>
Date: Tue, 15 Oct 2024 16:25:29 -0700
From: Kuniyuki Iwashima <kuniyu@...zon.com>
To: <gnaaman@...venets.com>
CC: <davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
<kuniyu@...zon.com>, <netdev@...r.kernel.org>, <pabeni@...hat.com>
Subject: Re: [PATCH net-next v4 3/6] Convert neigh_* seq_file functions to use hlist
From: Gilad Naaman <gnaaman@...venets.com>
Date: Tue, 15 Oct 2024 16:59:23 +0000
> Convert seq_file-related neighbour functionality to use neighbour::hash
> and the related for_each macro.
>
> Signed-off-by: Gilad Naaman <gnaaman@...venets.com>
> ---
> include/net/neighbour.h | 4 ++++
> net/core/neighbour.c | 26 ++++++++++----------------
> 2 files changed, 14 insertions(+), 16 deletions(-)
>
> diff --git a/include/net/neighbour.h b/include/net/neighbour.h
> index 2f4cb9e51364..7dc0d4d6a4a8 100644
> --- a/include/net/neighbour.h
> +++ b/include/net/neighbour.h
> @@ -279,6 +279,10 @@ static inline void *neighbour_priv(const struct neighbour *n)
> extern const struct nla_policy nda_policy[];
>
> #define neigh_for_each(pos, head) hlist_for_each_entry(pos, head, hash)
> +#define neigh_hlist_entry(n) hlist_entry_safe(n, struct neighbour, hash)
> +#define neigh_first_rcu(bucket) \
> + neigh_hlist_entry(rcu_dereference(hlist_first_rcu(bucket)))
No RCU helpers are needed, seq file is under RCU & tbl->lock
#define neigh_first_entry(bucket) \
hlist_entry_safe((bucket)->first, struct neighbour, hash)
> +
nit: unnecessary newline.
>
> static inline bool neigh_key_eq32(const struct neighbour *n, const void *pkey)
> {
> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index e91105a4c5ee..4bdf7649ca57 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -3207,25 +3207,21 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
>
> state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
> for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
> - n = rcu_dereference(nht->hash_buckets[bucket]);
> -
> - while (n) {
> + neigh_for_each(n, &nht->hash_heads[bucket]) {
> if (!net_eq(dev_net(n->dev), net))
> - goto next;
> + continue;
> if (state->neigh_sub_iter) {
> loff_t fakep = 0;
> void *v;
>
> v = state->neigh_sub_iter(state, n, &fakep);
> if (!v)
> - goto next;
> + continue;
> }
> if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
> break;
Let's avoid double-break and use goto just before setting bucket like:
out:
state->bucket = bucket
> if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
> break;
Same here.
> -next:
> - n = rcu_dereference(n->next);
> }
>
> if (n)
Then, this null check & break will be unnecessary.
> @@ -3249,34 +3245,32 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
> if (v)
> return n;
> }
> - n = rcu_dereference(n->next);
>
> while (1) {
> - while (n) {
> + hlist_for_each_entry_continue_rcu(n, hash) {
> if (!net_eq(dev_net(n->dev), net))
> - goto next;
> + continue;
> if (state->neigh_sub_iter) {
> void *v = state->neigh_sub_iter(state, n, pos);
> if (v)
> return n;
> - goto next;
> + continue;
> }
> if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
> break;
>
> if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
> break;
Same remark here.
> -next:
> - n = rcu_dereference(n->next);
> }
>
> if (n)
> break;
and here.
>
> - if (++state->bucket >= (1 << nht->hash_shift))
> - break;
Let's keep this,
> + while (!n && ++state->bucket < (1 << nht->hash_shift))
> + n = neigh_first_rcu(&nht->hash_heads[state->bucket]);
>
> - n = rcu_dereference(nht->hash_buckets[state->bucket]);
and simply fetch neigh_first_entry().
Then, we can let the next loop handle the termination condition
and keep the code simple.
> + if (!n)
> + break;
> }
>
> if (n && pos)
> --
> 2.46.0
Powered by blists - more mailing lists