diff options
author | Kuniyuki Iwashima <kuniyu@google.com> | 2025-07-16 22:08:15 +0000 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2025-07-17 16:25:21 -0700 |
commit | 32d5eaabf186112eb2023aacb860c47ff7e7fdbf (patch) | |
tree | 2ee733c4b912188c16070d33831a88cae7f15e79 | |
parent | ed6e380d2d419a3e8ca73de7b4c7ccb522835f1e (diff) |
neighbour: Drop read_lock_bh(&tbl->lock) in pneigh_dump_table().
Now pneigh_entry is guaranteed to be alive during the
RCU critical section even without holding tbl->lock.
Let's drop read_lock_bh(&tbl->lock) and use rcu_dereference()
to iterate tbl->phash_buckets[] in pneigh_dump_table()
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250716221221.442239-11-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | net/core/neighbour.c | 11 |
1 files changed, 3 insertions, 8 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 50ab95ecbcd6..3ef797212618 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2808,14 +2808,12 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, if (filter->dev_idx || filter->master_idx) flags |= NLM_F_DUMP_FILTERED; - read_lock_bh(&tbl->lock); - for (h = s_h; h <= PNEIGH_HASHMASK; h++) { if (h > s_h) s_idx = 0; - for (n = rcu_dereference_protected(tbl->phash_buckets[h], 1), idx = 0; + for (n = rcu_dereference(tbl->phash_buckets[h]), idx = 0; n; - n = rcu_dereference_protected(n->next, 1)) { + n = rcu_dereference(n->next)) { if (idx < s_idx || pneigh_net(n) != net) goto next; if (neigh_ifindex_filtered(n->dev, filter->dev_idx) || @@ -2824,16 +2822,13 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, err = pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, flags, tbl); - if (err < 0) { - read_unlock_bh(&tbl->lock); + if (err < 0) goto out; - } next: idx++; } } - read_unlock_bh(&tbl->lock); out: cb->args[3] = h; cb->args[4] = idx; |