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 <[email protected]> --- net/bridge/br_vlan.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index dcf783e1a440..c4e7e03e0969 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -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) { -- 2.47.3
