From fc73b71c1bdbf293d3fca7158424d6117466d4f8 Mon Sep 17 00:00:00 2001 From: Wang Zhan Date: Thu, 3 Sep 2026 21:33:13 +0800 Subject: [PATCH] net: sysfs: factor out link settings read speed_show() and duplex_show() duplicate device validation, RTNL locking and the link settings query. Move this common work to sysfs_get_link_ksettings() so later locking changes stay in one place. RTNL is released before calling sysfs_emit(). The lock only protects the link settings query; formatting uses the local cmd copy, so the sysfs output and error handling remain unchanged. No functional changes. Assisted-by: LLM Signed-off-by: Wang Zhan Link: https://patch.msgid.link/20260903133314.3703381-2-wang.zhan@smartx.com Signed-off-by: Paolo Abeni --- net/core/net-sysfs.c | 97 ++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 352173df7578..7bb8bbc1f71e 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -118,6 +118,34 @@ unbreak: return ret; } +static int sysfs_get_link_ksettings(struct device *dev, + struct device_attribute *attr, + struct ethtool_link_ksettings *cmd) +{ + struct net_device *netdev = to_net_dev(dev); + int ret; + + /* + * The check is also done in __ethtool_get_link_ksettings; this helps + * returning early without hitting the locking section below. + */ + if (!netdev->ethtool_ops->get_link_ksettings) + return -EINVAL; + + ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev); + if (ret) + return ret; + + ret = -EINVAL; + if (netif_running(netdev)) { + if (!__ethtool_get_link_ksettings(netdev, cmd)) + ret = 0; + } + + rtnl_unlock(); + return ret; +} + /* use same locking rules as GIF* ioctl's */ static ssize_t netdev_show(const struct device *dev, struct device_attribute *attr, char *buf, @@ -332,70 +360,41 @@ static DEVICE_ATTR_RW(carrier); static ssize_t speed_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - int ret = -EINVAL; + struct ethtool_link_ksettings cmd; + int ret; - /* The check is also done in __ethtool_get_link_ksettings; this helps - * returning early without hitting the locking section below. - */ - if (!netdev->ethtool_ops->get_link_ksettings) - return ret; - - ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev); + ret = sysfs_get_link_ksettings(dev, attr, &cmd); if (ret) return ret; - ret = -EINVAL; - if (netif_running(netdev)) { - struct ethtool_link_ksettings cmd; - - if (!__ethtool_get_link_ksettings(netdev, &cmd)) - ret = sysfs_emit(buf, fmt_dec, cmd.base.speed); - } - rtnl_unlock(); - return ret; + return sysfs_emit(buf, fmt_dec, cmd.base.speed); } static DEVICE_ATTR_RO(speed); static ssize_t duplex_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - int ret = -EINVAL; + struct ethtool_link_ksettings cmd; + const char *duplex; + int ret; - /* The check is also done in __ethtool_get_link_ksettings; this helps - * returning early without hitting the locking section below. - */ - if (!netdev->ethtool_ops->get_link_ksettings) - return ret; - - ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev); + ret = sysfs_get_link_ksettings(dev, attr, &cmd); if (ret) return ret; - ret = -EINVAL; - if (netif_running(netdev)) { - struct ethtool_link_ksettings cmd; - - if (!__ethtool_get_link_ksettings(netdev, &cmd)) { - const char *duplex; - - switch (cmd.base.duplex) { - case DUPLEX_HALF: - duplex = "half"; - break; - case DUPLEX_FULL: - duplex = "full"; - break; - default: - duplex = "unknown"; - break; - } - ret = sysfs_emit(buf, "%s\n", duplex); - } + switch (cmd.base.duplex) { + case DUPLEX_HALF: + duplex = "half"; + break; + case DUPLEX_FULL: + duplex = "full"; + break; + default: + duplex = "unknown"; + break; } - rtnl_unlock(); - return ret; + + return sysfs_emit(buf, "%s\n", duplex); } static DEVICE_ATTR_RO(duplex);