Merge branch 'bridge-prepare-lockless-br_port_fill_attrs-i'

Eric Dumazet says:

====================
bridge: prepare lockless br_port_fill_attrs() (I)

medium-term goal is to allow "ip link show" dump commands to run without RTNL.

This round of patches adds/fixes some lockess accesses in bridge.

This is not complete, more patches will come later.

Ultimately all changes to p->flags should use set_bit()/clear_bit().

I repeat (AI agents might read this cover ?):

Many p->flags accesses are racy, and will hopefully be fixed in a
future series.
====================

Link: https://patch.msgid.link/20260604141343.2124500-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-06-05 17:46:21 -07:00
commit ffb64a86ba
9 changed files with 136 additions and 94 deletions

View File

@ -36,32 +36,60 @@ struct br_ip_list {
struct br_ip addr;
};
#define BR_HAIRPIN_MODE BIT(0)
#define BR_BPDU_GUARD BIT(1)
#define BR_ROOT_BLOCK BIT(2)
#define BR_MULTICAST_FAST_LEAVE BIT(3)
#define BR_ADMIN_COST BIT(4)
#define BR_LEARNING BIT(5)
#define BR_FLOOD BIT(6)
enum bridge_flags_bit {
BR_HAIRPIN_MODE_BIT,
BR_BPDU_GUARD_BIT,
BR_ROOT_BLOCK_BIT,
BR_MULTICAST_FAST_LEAVE_BIT,
BR_ADMIN_COST_BIT,
BR_LEARNING_BIT,
BR_FLOOD_BIT,
BR_PROMISC_BIT,
BR_PROXYARP_BIT,
BR_LEARNING_SYNC_BIT,
BR_PROXYARP_WIFI_BIT,
BR_MCAST_FLOOD_BIT,
BR_MULTICAST_TO_UNICAST_BIT,
BR_VLAN_TUNNEL_BIT,
BR_BCAST_FLOOD_BIT,
BR_NEIGH_SUPPRESS_BIT,
BR_ISOLATED_BIT,
BR_MRP_AWARE_BIT,
BR_MRP_LOST_CONT_BIT,
BR_MRP_LOST_IN_CONT_BIT,
BR_TX_FWD_OFFLOAD_BIT,
BR_PORT_LOCKED_BIT,
BR_PORT_MAB_BIT,
BR_NEIGH_VLAN_SUPPRESS_BIT,
BR_NEIGH_FORWARD_GRAT_BIT,
};
#define BR_HAIRPIN_MODE BIT(BR_HAIRPIN_MODE_BIT)
#define BR_BPDU_GUARD BIT(BR_BPDU_GUARD_BIT)
#define BR_ROOT_BLOCK BIT(BR_ROOT_BLOCK_BIT)
#define BR_MULTICAST_FAST_LEAVE BIT(BR_MULTICAST_FAST_LEAVE_BIT)
#define BR_ADMIN_COST BIT(BR_ADMIN_COST_BIT)
#define BR_LEARNING BIT(BR_LEARNING_BIT)
#define BR_FLOOD BIT(BR_FLOOD_BIT)
#define BR_AUTO_MASK (BR_FLOOD | BR_LEARNING)
#define BR_PROMISC BIT(7)
#define BR_PROXYARP BIT(8)
#define BR_LEARNING_SYNC BIT(9)
#define BR_PROXYARP_WIFI BIT(10)
#define BR_MCAST_FLOOD BIT(11)
#define BR_MULTICAST_TO_UNICAST BIT(12)
#define BR_VLAN_TUNNEL BIT(13)
#define BR_BCAST_FLOOD BIT(14)
#define BR_NEIGH_SUPPRESS BIT(15)
#define BR_ISOLATED BIT(16)
#define BR_MRP_AWARE BIT(17)
#define BR_MRP_LOST_CONT BIT(18)
#define BR_MRP_LOST_IN_CONT BIT(19)
#define BR_TX_FWD_OFFLOAD BIT(20)
#define BR_PORT_LOCKED BIT(21)
#define BR_PORT_MAB BIT(22)
#define BR_NEIGH_VLAN_SUPPRESS BIT(23)
#define BR_NEIGH_FORWARD_GRAT BIT(24)
#define BR_PROMISC BIT(BR_PROMISC_BIT)
#define BR_PROXYARP BIT(BR_PROXYARP_BIT)
#define BR_LEARNING_SYNC BIT(BR_LEARNING_SYNC_BIT)
#define BR_PROXYARP_WIFI BIT(BR_PROXYARP_WIFI_BIT)
#define BR_MCAST_FLOOD BIT(BR_MCAST_FLOOD_BIT)
#define BR_MULTICAST_TO_UNICAST BIT(BR_MULTICAST_TO_UNICAST_BIT)
#define BR_VLAN_TUNNEL BIT(BR_VLAN_TUNNEL_BIT)
#define BR_BCAST_FLOOD BIT(BR_BCAST_FLOOD_BIT)
#define BR_NEIGH_SUPPRESS BIT(BR_NEIGH_SUPPRESS_BIT)
#define BR_ISOLATED BIT(BR_ISOLATED_BIT)
#define BR_MRP_AWARE BIT(BR_MRP_AWARE_BIT)
#define BR_MRP_LOST_CONT BIT(BR_MRP_LOST_CONT_BIT)
#define BR_MRP_LOST_IN_CONT BIT(BR_MRP_LOST_IN_CONT_BIT)
#define BR_TX_FWD_OFFLOAD BIT(BR_TX_FWD_OFFLOAD_BIT)
#define BR_PORT_LOCKED BIT(BR_PORT_LOCKED_BIT)
#define BR_PORT_MAB BIT(BR_PORT_MAB_BIT)
#define BR_NEIGH_VLAN_SUPPRESS BIT(BR_NEIGH_VLAN_SUPPRESS_BIT)
#define BR_NEIGH_FORWARD_GRAT BIT(BR_NEIGH_FORWARD_GRAT_BIT)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)

View File

@ -76,9 +76,9 @@ void br_port_carrier_check(struct net_bridge_port *p, bool *notified)
struct net_device *dev = p->dev;
struct net_bridge *br = p->br;
if (!(p->flags & BR_ADMIN_COST) &&
if (!test_bit(BR_ADMIN_COST_BIT, &p->flags) &&
netif_running(dev) && netif_oper_up(dev))
p->path_cost = port_cost(dev);
WRITE_ONCE(p->path_cost, port_cost(dev));
*notified = false;
if (!netif_running(br->dev))
@ -111,7 +111,7 @@ static void br_port_set_promisc(struct net_bridge_port *p)
return;
br_fdb_unsync_static(p->br, p);
p->flags |= BR_PROMISC;
set_bit(BR_PROMISC_BIT, &p->flags);
}
static void br_port_clear_promisc(struct net_bridge_port *p)
@ -134,7 +134,7 @@ static void br_port_clear_promisc(struct net_bridge_port *p)
return;
dev_set_promiscuity(p->dev, -1);
p->flags &= ~BR_PROMISC;
clear_bit(BR_PROMISC_BIT, &p->flags);
}
/* When a port is added or removed or when certain port flags

View File

@ -257,13 +257,13 @@ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
memset(&p, 0, sizeof(struct __port_info));
memcpy(&p.designated_root, &pt->designated_root, 8);
memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
p.port_id = pt->port_id;
p.designated_port = pt->designated_port;
p.path_cost = pt->path_cost;
p.designated_cost = pt->designated_cost;
p.port_id = READ_ONCE(pt->port_id);
p.designated_port = READ_ONCE(pt->designated_port);
p.path_cost = READ_ONCE(pt->path_cost);
p.designated_cost = READ_ONCE(pt->designated_cost);
p.state = pt->state;
p.top_change_ack = pt->topology_change_ack;
p.config_pending = pt->config_pending;
p.config_pending = READ_ONCE(pt->config_pending);
p.message_age_timer_value = br_timer_value(&pt->message_age_timer);
p.forward_delay_timer_value = br_timer_value(&pt->forward_delay_timer);
p.hold_timer_value = br_timer_value(&pt->hold_timer);

View File

@ -234,58 +234,61 @@ static inline size_t br_nlmsg_size(struct net_device *dev, u32 filter_mask)
static int br_port_fill_attrs(struct sk_buff *skb,
const struct net_bridge_port *p)
{
u8 mode = !!(p->flags & BR_HAIRPIN_MODE);
unsigned long flags = READ_ONCE(p->flags);
u8 mode = !!(flags & BR_HAIRPIN_MODE);
struct net_bridge_port *backup_p;
u64 timerval;
if (nla_put_u8(skb, IFLA_BRPORT_STATE, p->state) ||
nla_put_u16(skb, IFLA_BRPORT_PRIORITY, p->priority) ||
nla_put_u32(skb, IFLA_BRPORT_COST, p->path_cost) ||
nla_put_u16(skb, IFLA_BRPORT_PRIORITY, READ_ONCE(p->priority)) ||
nla_put_u32(skb, IFLA_BRPORT_COST, READ_ONCE(p->path_cost)) ||
nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||
nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(flags & BR_BPDU_GUARD)) ||
nla_put_u8(skb, IFLA_BRPORT_PROTECT,
!!(p->flags & BR_ROOT_BLOCK)) ||
!!(flags & BR_ROOT_BLOCK)) ||
nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE,
!!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
!!(flags & BR_MULTICAST_FAST_LEAVE)) ||
nla_put_u8(skb, IFLA_BRPORT_MCAST_TO_UCAST,
!!(p->flags & BR_MULTICAST_TO_UNICAST)) ||
nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
!!(flags & BR_MULTICAST_TO_UNICAST)) ||
nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(flags & BR_LEARNING)) ||
nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
!!(p->flags & BR_FLOOD)) ||
!!(flags & BR_FLOOD)) ||
nla_put_u8(skb, IFLA_BRPORT_MCAST_FLOOD,
!!(p->flags & BR_MCAST_FLOOD)) ||
!!(flags & BR_MCAST_FLOOD)) ||
nla_put_u8(skb, IFLA_BRPORT_BCAST_FLOOD,
!!(p->flags & BR_BCAST_FLOOD)) ||
nla_put_u8(skb, IFLA_BRPORT_PROXYARP, !!(p->flags & BR_PROXYARP)) ||
!!(flags & BR_BCAST_FLOOD)) ||
nla_put_u8(skb, IFLA_BRPORT_PROXYARP, !!(flags & BR_PROXYARP)) ||
nla_put_u8(skb, IFLA_BRPORT_PROXYARP_WIFI,
!!(p->flags & BR_PROXYARP_WIFI)) ||
!!(flags & BR_PROXYARP_WIFI)) ||
nla_put(skb, IFLA_BRPORT_ROOT_ID, sizeof(struct ifla_bridge_id),
&p->designated_root) ||
nla_put(skb, IFLA_BRPORT_BRIDGE_ID, sizeof(struct ifla_bridge_id),
&p->designated_bridge) ||
nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_PORT, p->designated_port) ||
nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_COST, p->designated_cost) ||
nla_put_u16(skb, IFLA_BRPORT_ID, p->port_id) ||
nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_PORT,
READ_ONCE(p->designated_port)) ||
nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_COST,
READ_ONCE(p->designated_cost)) ||
nla_put_u16(skb, IFLA_BRPORT_ID, READ_ONCE(p->port_id)) ||
nla_put_u16(skb, IFLA_BRPORT_NO, p->port_no) ||
nla_put_u8(skb, IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
p->topology_change_ack) ||
nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) ||
nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags &
nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, READ_ONCE(p->config_pending)) ||
nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(flags &
BR_VLAN_TUNNEL)) ||
nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) ||
nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS,
!!(p->flags & BR_NEIGH_SUPPRESS)) ||
nla_put_u8(skb, IFLA_BRPORT_MRP_RING_OPEN, !!(p->flags &
!!(flags & BR_NEIGH_SUPPRESS)) ||
nla_put_u8(skb, IFLA_BRPORT_MRP_RING_OPEN, !!(flags &
BR_MRP_LOST_CONT)) ||
nla_put_u8(skb, IFLA_BRPORT_MRP_IN_OPEN,
!!(p->flags & BR_MRP_LOST_IN_CONT)) ||
nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)) ||
nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED)) ||
nla_put_u8(skb, IFLA_BRPORT_MAB, !!(p->flags & BR_PORT_MAB)) ||
!!(flags & BR_MRP_LOST_IN_CONT)) ||
nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(flags & BR_ISOLATED)) ||
nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(flags & BR_PORT_LOCKED)) ||
nla_put_u8(skb, IFLA_BRPORT_MAB, !!(flags & BR_PORT_MAB)) ||
nla_put_u8(skb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
!!(p->flags & BR_NEIGH_VLAN_SUPPRESS)) ||
!!(flags & BR_NEIGH_VLAN_SUPPRESS)) ||
nla_put_u8(skb, IFLA_BRPORT_NEIGH_FORWARD_GRAT,
!!(p->flags & BR_NEIGH_FORWARD_GRAT)))
!!(flags & BR_NEIGH_FORWARD_GRAT)))
return -EMSGSIZE;
timerval = br_timer_value(&p->message_age_timer);

View File

@ -452,7 +452,7 @@ struct net_bridge_port {
#define kobj_to_brport(obj) container_of(obj, struct net_bridge_port, kobj)
#define br_auto_port(p) ((p)->flags & BR_AUTO_MASK)
#define br_promisc_port(p) ((p)->flags & BR_PROMISC)
#define br_promisc_port(p) test_bit(BR_PROMISC_BIT, &(p)->flags)
static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
{

View File

@ -102,8 +102,9 @@ struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
static int br_should_become_root_port(const struct net_bridge_port *p,
u16 root_port)
{
struct net_bridge *br;
u32 p_path_cost, rp_path_cost, p_designated_cost, rp_designated_cost;
struct net_bridge_port *rp;
struct net_bridge *br;
int t;
br = p->br;
@ -125,11 +126,16 @@ static int br_should_become_root_port(const struct net_bridge_port *p,
else if (t > 0)
return 0;
if (p->designated_cost + p->path_cost <
rp->designated_cost + rp->path_cost)
p_path_cost = READ_ONCE(p->path_cost);
rp_path_cost = READ_ONCE(rp->path_cost);
p_designated_cost = READ_ONCE(p->designated_cost);
rp_designated_cost = READ_ONCE(rp->designated_cost);
if (p_designated_cost + p_path_cost <
rp_designated_cost + rp_path_cost)
return 1;
else if (p->designated_cost + p->path_cost >
rp->designated_cost + rp->path_cost)
else if (p_designated_cost + p_path_cost >
rp_designated_cost + rp_path_cost)
return 0;
t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
@ -187,7 +193,8 @@ static void br_root_selection(struct net_bridge *br)
} else {
p = br_get_port(br, root_port);
br->designated_root = p->designated_root;
br->root_path_cost = p->designated_cost + p->path_cost;
br->root_path_cost = READ_ONCE(p->designated_cost) +
READ_ONCE(p->path_cost);
}
}
@ -213,7 +220,7 @@ void br_transmit_config(struct net_bridge_port *p)
struct net_bridge *br;
if (timer_pending(&p->hold_timer)) {
p->config_pending = 1;
WRITE_ONCE(p->config_pending, 1);
return;
}
@ -240,7 +247,7 @@ void br_transmit_config(struct net_bridge_port *p)
if (bpdu.message_age < br->max_age) {
br_send_config_bpdu(p, &bpdu);
p->topology_change_ack = 0;
p->config_pending = 0;
WRITE_ONCE(p->config_pending, 0);
if (p->br->stp_enabled == BR_KERNEL_STP)
mod_timer(&p->hold_timer,
round_jiffies(jiffies + BR_HOLD_TIME));
@ -252,9 +259,9 @@ static void br_record_config_information(struct net_bridge_port *p,
const struct br_config_bpdu *bpdu)
{
p->designated_root = bpdu->root;
p->designated_cost = bpdu->root_path_cost;
WRITE_ONCE(p->designated_cost, bpdu->root_path_cost);
p->designated_bridge = bpdu->bridge_id;
p->designated_port = bpdu->port_id;
WRITE_ONCE(p->designated_port, bpdu->port_id);
p->designated_age = jiffies - bpdu->message_age;
mod_timer(&p->message_age_timer, jiffies
@ -288,6 +295,7 @@ void br_transmit_tcn(struct net_bridge *br)
static int br_should_become_designated_port(const struct net_bridge_port *p)
{
struct net_bridge *br;
u32 p_designated_cost;
int t;
br = p->br;
@ -297,9 +305,10 @@ static int br_should_become_designated_port(const struct net_bridge_port *p)
if (memcmp(&p->designated_root, &br->designated_root, 8))
return 1;
if (br->root_path_cost < p->designated_cost)
p_designated_cost = READ_ONCE(p->designated_cost);
if (br->root_path_cost < p_designated_cost)
return 1;
else if (br->root_path_cost > p->designated_cost)
else if (br->root_path_cost > p_designated_cost)
return 0;
t = memcmp(&br->bridge_id, &p->designated_bridge, 8);
@ -331,6 +340,7 @@ static void br_designated_port_selection(struct net_bridge *br)
static int br_supersedes_port_info(const struct net_bridge_port *p,
const struct br_config_bpdu *bpdu)
{
u32 p_designated_cost;
int t;
t = memcmp(&bpdu->root, &p->designated_root, 8);
@ -339,9 +349,10 @@ static int br_supersedes_port_info(const struct net_bridge_port *p,
else if (t > 0)
return 0;
if (bpdu->root_path_cost < p->designated_cost)
p_designated_cost = READ_ONCE(p->designated_cost);
if (bpdu->root_path_cost < p_designated_cost)
return 1;
else if (bpdu->root_path_cost > p->designated_cost)
else if (bpdu->root_path_cost > p_designated_cost)
return 0;
t = memcmp(&bpdu->bridge_id, &p->designated_bridge, 8);
@ -421,9 +432,9 @@ void br_become_designated_port(struct net_bridge_port *p)
br = p->br;
p->designated_root = br->designated_root;
p->designated_cost = br->root_path_cost;
WRITE_ONCE(p->designated_cost, br->root_path_cost);
p->designated_bridge = br->bridge_id;
p->designated_port = p->port_id;
WRITE_ONCE(p->designated_port, p->port_id);
}
@ -479,14 +490,14 @@ void br_port_state_selection(struct net_bridge *br)
/* Don't change port states if userspace is handling STP */
if (br->stp_enabled != BR_USER_STP) {
if (p->port_no == br->root_port) {
p->config_pending = 0;
WRITE_ONCE(p->config_pending, 0);
p->topology_change_ack = 0;
br_make_forwarding(p);
} else if (br_is_designated_port(p)) {
timer_delete(&p->message_age_timer);
br_make_forwarding(p);
} else {
p->config_pending = 0;
WRITE_ONCE(p->config_pending, 0);
p->topology_change_ack = 0;
br_make_blocking(p);
}

View File

@ -34,11 +34,11 @@ void br_init_port(struct net_bridge_port *p)
{
int err;
p->port_id = br_make_port_id(p->priority, p->port_no);
WRITE_ONCE(p->port_id, br_make_port_id(p->priority, p->port_no));
br_become_designated_port(p);
br_set_state(p, BR_STATE_BLOCKING);
p->topology_change_ack = 0;
p->config_pending = 0;
WRITE_ONCE(p->config_pending, 0);
err = __set_ageing_time(p->dev, p->br->ageing_time);
if (err)
@ -105,7 +105,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
br_become_designated_port(p);
br_set_state(p, BR_STATE_DISABLED);
p->topology_change_ack = 0;
p->config_pending = 0;
WRITE_ONCE(p->config_pending, 0);
br_ifinfo_notify(RTM_NEWLINK, NULL, p);
@ -320,10 +320,10 @@ int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio)
new_port_id = br_make_port_id(newprio, p->port_no);
if (br_is_designated_port(p))
p->designated_port = new_port_id;
WRITE_ONCE(p->designated_port, new_port_id);
p->port_id = new_port_id;
p->priority = newprio;
WRITE_ONCE(p->port_id, new_port_id);
WRITE_ONCE(p->priority, newprio);
if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
p->port_id < p->designated_port) {
br_become_designated_port(p);
@ -340,8 +340,8 @@ int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost)
path_cost > BR_MAX_PATH_COST)
return -ERANGE;
p->flags |= BR_ADMIN_COST;
p->path_cost = path_cost;
set_bit(BR_ADMIN_COST_BIT, &p->flags);
WRITE_ONCE(p->path_cost, path_cost);
br_configuration_update(p->br);
br_port_state_selection(p->br);
return 0;

View File

@ -160,5 +160,5 @@ void br_stp_port_timer_init(struct net_bridge_port *p)
unsigned long br_timer_value(const struct timer_list *timer)
{
return timer_pending(timer)
? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0;
? jiffies_delta_to_clock_t(READ_ONCE(timer->expires) - jiffies) : 0;
}

View File

@ -83,7 +83,7 @@ static int store_flag(struct net_bridge_port *p, unsigned long v,
static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
{
return sysfs_emit(buf, "%d\n", p->path_cost);
return sysfs_emit(buf, "%d\n", READ_ONCE(p->path_cost));
}
static int store_path_cost(struct net_bridge_port *p, unsigned long v)
@ -100,7 +100,7 @@ static BRPORT_ATTR(path_cost, 0644, show_path_cost, store_path_cost);
static ssize_t show_priority(struct net_bridge_port *p, char *buf)
{
return sysfs_emit(buf, "%d\n", p->priority);
return sysfs_emit(buf, "%d\n", READ_ONCE(p->priority));
}
static int store_priority(struct net_bridge_port *p, unsigned long v)
@ -129,19 +129,19 @@ static BRPORT_ATTR(designated_bridge, 0444, show_designated_bridge, NULL);
static ssize_t show_designated_port(struct net_bridge_port *p, char *buf)
{
return sysfs_emit(buf, "%d\n", p->designated_port);
return sysfs_emit(buf, "%d\n", READ_ONCE(p->designated_port));
}
static BRPORT_ATTR(designated_port, 0444, show_designated_port, NULL);
static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf)
{
return sysfs_emit(buf, "%d\n", p->designated_cost);
return sysfs_emit(buf, "%d\n", READ_ONCE(p->designated_cost));
}
static BRPORT_ATTR(designated_cost, 0444, show_designated_cost, NULL);
static ssize_t show_port_id(struct net_bridge_port *p, char *buf)
{
return sysfs_emit(buf, "0x%x\n", p->port_id);
return sysfs_emit(buf, "0x%x\n", READ_ONCE(p->port_id));
}
static BRPORT_ATTR(port_id, 0444, show_port_id, NULL);
@ -160,7 +160,7 @@ static BRPORT_ATTR(change_ack, 0444, show_change_ack, NULL);
static ssize_t show_config_pending(struct net_bridge_port *p, char *buf)
{
return sysfs_emit(buf, "%d\n", p->config_pending);
return sysfs_emit(buf, "%d\n", READ_ONCE(p->config_pending));
}
static BRPORT_ATTR(config_pending, 0444, show_config_pending, NULL);