summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@nvidia.com>2025-04-15 15:11:38 +0300
committerPaolo Abeni <pabeni@redhat.com>2025-04-22 11:11:16 +0200
commit54f45187b635f8c4c1e554a2ed347bba7d27dfbd (patch)
treecbf719b3cf546502625ee82277c5c8af61271dad
parenta6d04f8937e3a721c3a3578fc18b28cb59b15f42 (diff)
vxlan: Convert FDB flushing to RCU
Instead of holding the FDB hash lock when traversing the FDB linked list during flushing, use RCU and only acquire the lock for entries that need to be flushed. Reviewed-by: Petr Machata <petrm@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20250415121143.345227-11-idosch@nvidia.com Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--drivers/net/vxlan/vxlan_core.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index c3511a43ce99..762dde70d9e9 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3037,14 +3037,17 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
const struct vxlan_fdb_flush_desc *desc)
{
bool match_remotes = vxlan_fdb_flush_should_match_remotes(desc);
- struct hlist_node *n;
struct vxlan_fdb *f;
- spin_lock_bh(&vxlan->hash_lock);
- hlist_for_each_entry_safe(f, n, &vxlan->fdb_list, fdb_node) {
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(f, &vxlan->fdb_list, fdb_node) {
if (!vxlan_fdb_flush_matches(f, vxlan, desc))
continue;
+ spin_lock_bh(&vxlan->hash_lock);
+ if (hlist_unhashed(&f->fdb_node))
+ goto unlock;
+
if (match_remotes) {
bool destroy_fdb = false;
@@ -3052,12 +3055,14 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
&destroy_fdb);
if (!destroy_fdb)
- continue;
+ goto unlock;
}
vxlan_fdb_destroy(vxlan, f, true, true);
+unlock:
+ spin_unlock_bh(&vxlan->hash_lock);
}
- spin_unlock_bh(&vxlan->hash_lock);
+ rcu_read_unlock();
}
static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {