]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net-sysfs: convert dev->operstate reads to lockless ones
authorEric Dumazet <edumazet@google.com>
Tue, 13 Feb 2024 06:32:39 +0000 (06:32 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 May 2024 10:02:23 +0000 (12:02 +0200)
[ Upstream commit 004d138364fd10dd5ff8ceb54cfdc2d792a7b338 ]

operstate_show() can omit dev_base_lock acquisition only
to read dev->operstate.

Annotate accesses to dev->operstate.

Writers still acquire dev_base_lock for mutual exclusion.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 4893b8b3ef8d ("hsr: Simplify code for announcing HSR nodes timer setup")
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/bridge/br_netlink.c
net/core/link_watch.c
net/core/net-sysfs.c
net/core/rtnetlink.c
net/hsr/hsr_device.c
net/ipv6/addrconf.c

index 65e9ed3851425ae89a3f427884859a946dcf6c78..4488faf059a363c5698cc8be8022ddfdf86a7083 100644 (file)
@@ -455,7 +455,8 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                          u32 filter_mask, const struct net_device *dev,
                          bool getlink)
 {
-       u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+       u8 operstate = netif_running(dev) ? READ_ONCE(dev->operstate) :
+                                           IF_OPER_DOWN;
        struct nlattr *af = NULL;
        struct net_bridge *br;
        struct ifinfomsg *hdr;
index c469d1c4db5d7a5d1fa3d4ae4a36f706c16bf25e..cb43f5aebfbccfe5e4e9c3f300eaed72a2b6f038 100644 (file)
@@ -67,7 +67,7 @@ static void rfc2863_policy(struct net_device *dev)
 {
        unsigned char operstate = default_operstate(dev);
 
-       if (operstate == dev->operstate)
+       if (operstate == READ_ONCE(dev->operstate))
                return;
 
        write_lock(&dev_base_lock);
@@ -87,7 +87,7 @@ static void rfc2863_policy(struct net_device *dev)
                break;
        }
 
-       dev->operstate = operstate;
+       WRITE_ONCE(dev->operstate, operstate);
 
        write_unlock(&dev_base_lock);
 }
index fccaa5bac0ed0a34a55bef1f4f6487a81285f286..5a9487af44e009d21c2d9afb2ec83837f35c6a01 100644 (file)
@@ -307,11 +307,9 @@ static ssize_t operstate_show(struct device *dev,
        const struct net_device *netdev = to_net_dev(dev);
        unsigned char operstate;
 
-       read_lock(&dev_base_lock);
-       operstate = netdev->operstate;
+       operstate = READ_ONCE(netdev->operstate);
        if (!netif_running(netdev))
                operstate = IF_OPER_DOWN;
-       read_unlock(&dev_base_lock);
 
        if (operstate >= ARRAY_SIZE(operstates))
                return -EINVAL; /* should not happen */
index 89964270cf27fc1bbcf7259fa652189ab9c63a29..7ea66de1442cc0ea55aaf82dfb218484902b9a4d 100644 (file)
@@ -880,9 +880,9 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
                break;
        }
 
-       if (dev->operstate != operstate) {
+       if (READ_ONCE(dev->operstate) != operstate) {
                write_lock(&dev_base_lock);
-               dev->operstate = operstate;
+               WRITE_ONCE(dev->operstate, operstate);
                write_unlock(&dev_base_lock);
                netdev_state_change(dev);
        }
index dd4b5f0aa1318c1501551a406cf7e3cc34fc09e5..cd337385e859267b34768ce7a003c866234dfb93 100644 (file)
@@ -31,8 +31,8 @@ static bool is_slave_up(struct net_device *dev)
 static void __hsr_set_operstate(struct net_device *dev, int transition)
 {
        write_lock(&dev_base_lock);
-       if (dev->operstate != transition) {
-               dev->operstate = transition;
+       if (READ_ONCE(dev->operstate) != transition) {
+               WRITE_ONCE(dev->operstate, transition);
                write_unlock(&dev_base_lock);
                netdev_state_change(dev);
        } else {
@@ -78,14 +78,14 @@ static void hsr_check_announce(struct net_device *hsr_dev,
 
        hsr = netdev_priv(hsr_dev);
 
-       if (hsr_dev->operstate == IF_OPER_UP && old_operstate != IF_OPER_UP) {
+       if (READ_ONCE(hsr_dev->operstate) == IF_OPER_UP && old_operstate != IF_OPER_UP) {
                /* Went up */
                hsr->announce_count = 0;
                mod_timer(&hsr->announce_timer,
                          jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL));
        }
 
-       if (hsr_dev->operstate != IF_OPER_UP && old_operstate == IF_OPER_UP)
+       if (READ_ONCE(hsr_dev->operstate) != IF_OPER_UP && old_operstate == IF_OPER_UP)
                /* Went down */
                del_timer(&hsr->announce_timer);
 }
@@ -100,7 +100,7 @@ void hsr_check_carrier_and_operstate(struct hsr_priv *hsr)
        /* netif_stacked_transfer_operstate() cannot be used here since
         * it doesn't set IF_OPER_LOWERLAYERDOWN (?)
         */
-       old_operstate = master->dev->operstate;
+       old_operstate = READ_ONCE(master->dev->operstate);
        has_carrier = hsr_check_carrier(master);
        hsr_set_operstate(master, has_carrier);
        hsr_check_announce(master->dev, old_operstate);
index d1806eee1687d6a2131c546dcd8d11653ea64952..01f4502916a12375518b2d093255abe21bce6429 100644 (file)
@@ -6011,7 +6011,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
            (dev->ifindex != dev_get_iflink(dev) &&
             nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
            nla_put_u8(skb, IFLA_OPERSTATE,
-                      netif_running(dev) ? dev->operstate : IF_OPER_DOWN))
+                      netif_running(dev) ? READ_ONCE(dev->operstate) : IF_OPER_DOWN))
                goto nla_put_failure;
        protoinfo = nla_nest_start_noflag(skb, IFLA_PROTINFO);
        if (!protoinfo)