Skip to content

Commit a6d04f8

Browse files
idoschPaolo Abeni
authored andcommitted
vxlan: Convert FDB garbage collection to RCU
Instead of holding the FDB hash lock when traversing the FDB linked list during garbage collection, use RCU and only acquire the lock for entries that need to be removed (aged out). Avoid races by using hlist_unhashed() to check that the entry has not been removed from the list by another thread. Note that vxlan_fdb_destroy() uses hlist_del_init_rcu() to remove an entry from the list which should cause list_unhashed() to return true. Reviewed-by: Petr Machata <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Nikolay Aleksandrov <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 7aa0dc7 commit a6d04f8

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

drivers/net/vxlan/vxlan_core.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2819,14 +2819,13 @@ static void vxlan_cleanup(struct timer_list *t)
28192819
{
28202820
struct vxlan_dev *vxlan = from_timer(vxlan, t, age_timer);
28212821
unsigned long next_timer = jiffies + FDB_AGE_INTERVAL;
2822-
struct hlist_node *n;
28232822
struct vxlan_fdb *f;
28242823

28252824
if (!netif_running(vxlan->dev))
28262825
return;
28272826

2828-
spin_lock(&vxlan->hash_lock);
2829-
hlist_for_each_entry_safe(f, n, &vxlan->fdb_list, fdb_node) {
2827+
rcu_read_lock();
2828+
hlist_for_each_entry_rcu(f, &vxlan->fdb_list, fdb_node) {
28302829
unsigned long timeout;
28312830

28322831
if (f->state & (NUD_PERMANENT | NUD_NOARP))
@@ -2837,15 +2836,19 @@ static void vxlan_cleanup(struct timer_list *t)
28372836

28382837
timeout = READ_ONCE(f->updated) + vxlan->cfg.age_interval * HZ;
28392838
if (time_before_eq(timeout, jiffies)) {
2840-
netdev_dbg(vxlan->dev, "garbage collect %pM\n",
2841-
f->eth_addr);
2842-
f->state = NUD_STALE;
2843-
vxlan_fdb_destroy(vxlan, f, true, true);
2839+
spin_lock(&vxlan->hash_lock);
2840+
if (!hlist_unhashed(&f->fdb_node)) {
2841+
netdev_dbg(vxlan->dev, "garbage collect %pM\n",
2842+
f->eth_addr);
2843+
f->state = NUD_STALE;
2844+
vxlan_fdb_destroy(vxlan, f, true, true);
2845+
}
2846+
spin_unlock(&vxlan->hash_lock);
28442847
} else if (time_before(timeout, next_timer)) {
28452848
next_timer = timeout;
28462849
}
28472850
}
2848-
spin_unlock(&vxlan->hash_lock);
2851+
rcu_read_unlock();
28492852

28502853
mod_timer(&vxlan->age_timer, next_timer);
28512854
}

0 commit comments

Comments
 (0)