diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 3e9b10f8abf1..8f84eb5b3cee 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -923,7 +923,7 @@ static void __br_multicast_query_handle_vlan(struct net_bridge_mcast *brmctx, else if (br_multicast_ctx_is_vlan(brmctx)) vlan = brmctx->vlan; - if (vlan && !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)) { + if (vlan && !(READ_ONCE(vlan->flags) & BRIDGE_VLAN_INFO_UNTAGGED)) { u16 vlan_proto; if (br_vlan_get_proto(brmctx->br->dev, &vlan_proto) != 0) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index b2cd4e39326d..62ce96d9ba32 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -41,7 +41,7 @@ static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg, if (v->vid == pvid) flags |= BRIDGE_VLAN_INFO_PVID; - if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) + if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED) flags |= BRIDGE_VLAN_INFO_UNTAGGED; if (vid_range_start == 0) { @@ -385,7 +385,7 @@ static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb, if (v->vid == pvid) flags |= BRIDGE_VLAN_INFO_PVID; - if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) + if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED) flags |= BRIDGE_VLAN_INFO_UNTAGGED; if (vid_range_start == 0) { @@ -437,7 +437,7 @@ static int br_fill_ifvlaninfo(struct sk_buff *skb, if (v->vid == pvid) vinfo.flags |= BRIDGE_VLAN_INFO_PVID; - if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) + if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED) vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO, diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 0efd2e79e255..96554d293d22 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -665,13 +665,13 @@ static inline int br_is_root_bridge(const struct net_bridge *br) /* check if a VLAN entry is global */ static inline bool br_vlan_is_master(const struct net_bridge_vlan *v) { - return v->flags & BRIDGE_VLAN_INFO_MASTER; + return READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_MASTER; } /* check if a VLAN entry is used by the bridge */ static inline bool br_vlan_is_brentry(const struct net_bridge_vlan *v) { - return v->flags & BRIDGE_VLAN_INFO_BRENTRY; + return READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_BRENTRY; } /* check if we should use the vlan entry, returns false if it's only context */ diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index a53054fcc093..c8b2e3bfd42d 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -60,6 +60,7 @@ static bool __vlan_flags_update(struct net_bridge_vlan *v, u16 flags, bool commit) { struct net_bridge_vlan_group *vg; + u16 vlan_flags; bool change; if (br_vlan_is_master(v)) @@ -68,8 +69,9 @@ static bool __vlan_flags_update(struct net_bridge_vlan *v, u16 flags, vg = nbp_vlan_group(v->port); /* check if anything would be changed on commit */ + vlan_flags = v->flags; change = !!(flags & BRIDGE_VLAN_INFO_PVID) == !!(vg->pvid != v->vid) || - ((flags ^ v->flags) & BRIDGE_VLAN_INFO_UNTAGGED); + ((flags ^ vlan_flags) & BRIDGE_VLAN_INFO_UNTAGGED); if (!commit) goto out; @@ -80,9 +82,10 @@ static bool __vlan_flags_update(struct net_bridge_vlan *v, u16 flags, __vlan_delete_pvid(vg, v->vid); if (flags & BRIDGE_VLAN_INFO_UNTAGGED) - v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; + vlan_flags |= BRIDGE_VLAN_INFO_UNTAGGED; else - v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; + vlan_flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; + WRITE_ONCE(v->flags, vlan_flags); out: return change; @@ -413,7 +416,7 @@ static int __vlan_del(struct net_bridge_vlan *v) } if (br_vlan_should_use(v)) { - v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY; + WRITE_ONCE(v->flags, v->flags & ~BRIDGE_VLAN_INFO_BRENTRY); vg->num_vlans--; } @@ -522,7 +525,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, * hardware on each egress port as appropriate. So only strip the VLAN * header if forwarding offload is not being used. */ - if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED && + if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED && !br_switchdev_frame_uses_tx_fwd_offload(skb)) __vlan_hwaccel_clear_tag(skb); @@ -753,7 +756,7 @@ static int br_vlan_add_existing(struct net_bridge *br, } refcount_inc(&vlan->refcnt); - vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY; + WRITE_ONCE(vlan->flags, vlan->flags | BRIDGE_VLAN_INFO_BRENTRY); vg->num_vlans++; *changed = true; br_multicast_toggle_one_vlan(vlan, true); @@ -1489,7 +1492,7 @@ int br_vlan_fill_forward_path_mode(struct net_bridge *br, if (!v || !br_vlan_should_use(v)) return -EINVAL; - if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) + if (!(READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED)) return 0; if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) @@ -1550,7 +1553,7 @@ int br_vlan_get_info_rcu(const struct net_device *dev, u16 vid, return -ENOENT; p_vinfo->vid = vid; - p_vinfo->flags = v->flags; + p_vinfo->flags = READ_ONCE(v->flags); if (vid == br_get_pvid(vg)) p_vinfo->flags |= BRIDGE_VLAN_INFO_PVID; return 0;