mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
net: bridge: vlan: split unpublishing from deletion
Split removal of a VLAN from its lookup and flood structures from object destruction. Pass the VLAN group explicitly to __vlan_del() and call both operations consecutively for now. This prepares deletion paths to quiesce readers after making an entry unreachable and before freeing it. Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org> Link: https://patch.msgid.link/20260930071411.2786201-8-razor@blackwall.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
f0a349b921
commit
e5c71bf914
|
|
@ -429,22 +429,34 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
|
|||
goto out;
|
||||
}
|
||||
|
||||
static void __vlan_del(struct net_bridge_vlan *v)
|
||||
static void __vlan_unpublish(struct net_bridge_vlan_group *vg,
|
||||
struct net_bridge_vlan *v)
|
||||
{
|
||||
__vlan_delete_pvid(vg, v);
|
||||
if (!br_vlan_is_master(v)) {
|
||||
struct net_bridge_vlan *masterv = v->brvlan;
|
||||
|
||||
rhashtable_remove_fast(&vg->vlan_hash, &v->vnode,
|
||||
br_vlan_rht_params);
|
||||
__vlan_del_list(v);
|
||||
/* -1 because br_vlan_put_master() is called later */
|
||||
br_vlan_rebuild_port_array(masterv,
|
||||
br_vlan_num_ports(masterv) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void __vlan_del(struct net_bridge_vlan_group *vg,
|
||||
struct net_bridge_vlan *v)
|
||||
{
|
||||
struct net_bridge_vlan *masterv = v;
|
||||
struct net_bridge_vlan_group *vg;
|
||||
struct net_bridge_port *p = NULL;
|
||||
int err;
|
||||
|
||||
if (br_vlan_is_master(v)) {
|
||||
vg = br_vlan_group(v->br);
|
||||
} else {
|
||||
if (!br_vlan_is_master(v)) {
|
||||
p = v->port;
|
||||
vg = nbp_vlan_group(v->port);
|
||||
masterv = v->brvlan;
|
||||
}
|
||||
|
||||
__vlan_delete_pvid(vg, v);
|
||||
if (p) {
|
||||
err = __vlan_vid_del(p->dev, p->br, v);
|
||||
if (err)
|
||||
|
|
@ -467,12 +479,6 @@ static void __vlan_del(struct net_bridge_vlan *v)
|
|||
|
||||
if (masterv != v) {
|
||||
vlan_tunnel_info_del(vg, v);
|
||||
rhashtable_remove_fast(&vg->vlan_hash, &v->vnode,
|
||||
br_vlan_rht_params);
|
||||
__vlan_del_list(v);
|
||||
/* -1 because br_vlan_put_master() is called later */
|
||||
br_vlan_rebuild_port_array(masterv,
|
||||
br_vlan_num_ports(masterv) - 1);
|
||||
nbp_vlan_set_vlan_dev_state(p, v->vid);
|
||||
br_multicast_toggle_one_vlan(v, false);
|
||||
br_multicast_port_ctx_deinit(&v->port_mcast_ctx);
|
||||
|
|
@ -509,7 +515,8 @@ static void __vlan_flush(const struct net_bridge *br,
|
|||
}
|
||||
v_end = vlan->vid;
|
||||
|
||||
__vlan_del(vlan);
|
||||
__vlan_unpublish(vg, vlan);
|
||||
__vlan_del(vg, vlan);
|
||||
}
|
||||
|
||||
/* notify about the last/whole vlan range */
|
||||
|
|
@ -873,7 +880,8 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
|
|||
br_fdb_cleanup_by_dst(br, br_port_to_dst(NULL), vid, 0);
|
||||
|
||||
vlan_tunnel_info_del(vg, v);
|
||||
__vlan_del(v);
|
||||
__vlan_unpublish(vg, v);
|
||||
__vlan_del(vg, v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1389,15 +1397,18 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
|
|||
*/
|
||||
int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
|
||||
{
|
||||
struct net_bridge_vlan_group *vg;
|
||||
struct net_bridge_vlan *v;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
v = br_vlan_find(nbp_vlan_group(port), vid);
|
||||
vg = nbp_vlan_group(port);
|
||||
v = br_vlan_find(vg, vid);
|
||||
if (!v)
|
||||
return -ENOENT;
|
||||
br_fdb_cleanup_by_dst(port->br, br_vlan_to_dst(v), vid, 0);
|
||||
__vlan_del(v);
|
||||
__vlan_unpublish(vg, v);
|
||||
__vlan_del(vg, v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user