net-sysfs: convert netdev_show() to RCU
authorEric Dumazet <edumazet@google.com>
Tue, 13 Feb 2024 06:32:37 +0000 (06:32 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 14 Feb 2024 11:20:13 +0000 (11:20 +0000)
Make clear dev_isalive() can be called with RCU protection.

Then convert netdev_show() to RCU, to remove dev_base_lock
dependency.

Also add RCU to broadcast_show().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/net-sysfs.c

index f4c2b82674951bbeefd880ca22c54e6a32c9f988..678e4be690821c5cdb933f5e91af2247ebecb830 100644 (file)
@@ -34,10 +34,10 @@ static const char fmt_dec[] = "%d\n";
 static const char fmt_ulong[] = "%lu\n";
 static const char fmt_u64[] = "%llu\n";
 
-/* Caller holds RTNL or dev_base_lock */
+/* Caller holds RTNL, RCU or dev_base_lock */
 static inline int dev_isalive(const struct net_device *dev)
 {
-       return dev->reg_state <= NETREG_REGISTERED;
+       return READ_ONCE(dev->reg_state) <= NETREG_REGISTERED;
 }
 
 /* use same locking rules as GIF* ioctl's */
@@ -48,10 +48,10 @@ static ssize_t netdev_show(const struct device *dev,
        struct net_device *ndev = to_net_dev(dev);
        ssize_t ret = -EINVAL;
 
-       read_lock(&dev_base_lock);
+       rcu_read_lock();
        if (dev_isalive(ndev))
                ret = (*format)(ndev, buf);
-       read_unlock(&dev_base_lock);
+       rcu_read_unlock();
 
        return ret;
 }
@@ -60,7 +60,7 @@ static ssize_t netdev_show(const struct device *dev,
 #define NETDEVICE_SHOW(field, format_string)                           \
 static ssize_t format_##field(const struct net_device *dev, char *buf) \
 {                                                                      \
-       return sysfs_emit(buf, format_string, dev->field);              \
+       return sysfs_emit(buf, format_string, READ_ONCE(dev->field));           \
 }                                                                      \
 static ssize_t field##_show(struct device *dev,                                \
                            struct device_attribute *attr, char *buf)   \
@@ -161,10 +161,13 @@ static ssize_t broadcast_show(struct device *dev,
                              struct device_attribute *attr, char *buf)
 {
        struct net_device *ndev = to_net_dev(dev);
+       int ret = -EINVAL;
 
+       rcu_read_lock();
        if (dev_isalive(ndev))
-               return sysfs_format_mac(buf, ndev->broadcast, ndev->addr_len);
-       return -EINVAL;
+               ret = sysfs_format_mac(buf, ndev->broadcast, ndev->addr_len);
+       rcu_read_unlock();
+       return ret;
 }
 static DEVICE_ATTR_RO(broadcast);