Commit 6890ab31 authored by Eric Dumazet's avatar Eric Dumazet Committed by Paolo Abeni

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: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 6747a5d4
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment