mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-27 04:47:05 +00:00
rtnetlink: do not depend on RTNL in rtnl_fill_proto_down()
Change dev_change_proto_down() and dev_change_proto_down_reason() to write once on dev->proto_down and dev->proto_down_reason. Then rtnl_fill_proto_down() can use READ_ONCE() annotations and run locklessly. rtnl_proto_down_size() should assume worst case, because readng dev->proto_down_reason multiple times would be racy without RTNL in the future. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
6747a5d499
commit
6890ab31d1
2 changed files with 11 additions and 8 deletions
|
@ -9223,7 +9223,7 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
|
|||
netif_carrier_off(dev);
|
||||
else
|
||||
netif_carrier_on(dev);
|
||||
dev->proto_down = proto_down;
|
||||
WRITE_ONCE(dev->proto_down, proto_down);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -9237,18 +9237,21 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
|
|||
void dev_change_proto_down_reason(struct net_device *dev, unsigned long mask,
|
||||
u32 value)
|
||||
{
|
||||
u32 proto_down_reason;
|
||||
int b;
|
||||
|
||||
if (!mask) {
|
||||
dev->proto_down_reason = value;
|
||||
proto_down_reason = value;
|
||||
} else {
|
||||
proto_down_reason = dev->proto_down_reason;
|
||||
for_each_set_bit(b, &mask, 32) {
|
||||
if (value & (1 << b))
|
||||
dev->proto_down_reason |= BIT(b);
|
||||
proto_down_reason |= BIT(b);
|
||||
else
|
||||
dev->proto_down_reason &= ~BIT(b);
|
||||
proto_down_reason &= ~BIT(b);
|
||||
}
|
||||
}
|
||||
WRITE_ONCE(dev->proto_down_reason, proto_down_reason);
|
||||
}
|
||||
|
||||
struct bpf_xdp_link {
|
||||
|
|
|
@ -1036,7 +1036,7 @@ static size_t rtnl_proto_down_size(const struct net_device *dev)
|
|||
{
|
||||
size_t size = nla_total_size(1);
|
||||
|
||||
if (dev->proto_down_reason)
|
||||
/* Assume dev->proto_down_reason is not zero. */
|
||||
size += nla_total_size(0) + nla_total_size(4);
|
||||
|
||||
return size;
|
||||
|
@ -1737,10 +1737,10 @@ static int rtnl_fill_proto_down(struct sk_buff *skb,
|
|||
struct nlattr *pr;
|
||||
u32 preason;
|
||||
|
||||
if (nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down))
|
||||
if (nla_put_u8(skb, IFLA_PROTO_DOWN, READ_ONCE(dev->proto_down)))
|
||||
goto nla_put_failure;
|
||||
|
||||
preason = dev->proto_down_reason;
|
||||
preason = READ_ONCE(dev->proto_down_reason);
|
||||
if (!preason)
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue