net: bridge: vlan: inline pvid pointer updates

After caching the pvid VLAN entry directly, the add and delete helpers
only check and update the pointer. So inline them both and clear pvid
directly in __vlan_flush before walking the VLAN entries.

Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20261005143937.877466-5-razor@blackwall.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Nikolay Aleksandrov 2026-10-05 17:39:35 +03:00 committed by Jakub Kicinski
parent 33c73892ea
commit 1fbe2d9d37

View File

@ -34,24 +34,6 @@ static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid)
return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params);
}
static void __vlan_add_pvid(struct net_bridge_vlan_group *vg,
struct net_bridge_vlan *v)
{
if (rcu_access_pointer(vg->pvid) == v)
return;
RCU_INIT_POINTER(vg->pvid, v);
}
static void __vlan_delete_pvid(struct net_bridge_vlan_group *vg,
struct net_bridge_vlan *v)
{
if (rcu_access_pointer(vg->pvid) != v)
return;
RCU_INIT_POINTER(vg->pvid, NULL);
}
/* Update the BRIDGE_VLAN_INFO_PVID and BRIDGE_VLAN_INFO_UNTAGGED flags of @v.
* If @commit is false, return just whether the BRIDGE_VLAN_INFO_PVID and
* BRIDGE_VLAN_INFO_UNTAGGED bits of @flags would produce any change onto @v.
@ -78,10 +60,12 @@ static bool __vlan_flags_update(struct net_bridge_vlan *v, u16 flags,
if (!commit)
goto out;
if (flags & BRIDGE_VLAN_INFO_PVID)
__vlan_add_pvid(vg, v);
else
__vlan_delete_pvid(vg, v);
if (flags & BRIDGE_VLAN_INFO_PVID) {
if (pvid != v)
RCU_INIT_POINTER(vg->pvid, v);
} else if (pvid == v) {
RCU_INIT_POINTER(vg->pvid, NULL);
}
if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
vlan_flags |= BRIDGE_VLAN_INFO_UNTAGGED;
@ -432,7 +416,8 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
static void __vlan_unpublish(struct net_bridge_vlan_group *vg,
struct net_bridge_vlan *v)
{
__vlan_delete_pvid(vg, v);
if (rcu_access_pointer(vg->pvid) == v)
RCU_INIT_POINTER(vg->pvid, NULL);
if (!br_vlan_is_master(v)) {
struct net_bridge_vlan *masterv = v->brvlan;
@ -503,7 +488,7 @@ static void __vlan_flush(const struct net_bridge *br,
struct net_bridge_vlan *vlan, *tmp;
u16 v_start = 0, v_end = 0;
__vlan_delete_pvid(vg, rtnl_dereference(vg->pvid));
RCU_INIT_POINTER(vg->pvid, NULL);
list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) {
/* take care of disjoint ranges */
if (!v_start) {