bonding: use rcu_dereference_rtnl when get bonding active slave
authorHangbin Liu <liuhangbin@gmail.com>
Fri, 21 Jan 2022 08:25:18 +0000 (16:25 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 24 Jan 2022 11:57:38 +0000 (11:57 +0000)
bond_option_active_slave_get_rcu() should not be used in rtnl_mutex as it
use rcu_dereference(). Replace to rcu_dereference_rtnl() so we also can use
this function in rtnl protected context.

With this update, we can rmeove the rcu_read_lock/unlock in
bonding .ndo_eth_ioctl and .get_ts_info.

Reported-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Fixes: 94dd016ae538 ("bond: pass get_ts_info and SIOC[SG]HWTSTAMP ioctl to active device")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bonding/bond_main.c
include/net/bonding.h

index ec498ce70f35a67a8b4c93bcae28312c7be6bf33..238b56d77c369d9595d55bc681c2191c49dd2905 100644 (file)
@@ -4133,9 +4133,7 @@ static int bond_eth_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cm
 
                fallthrough;
        case SIOCGHWTSTAMP:
-               rcu_read_lock();
                real_dev = bond_option_active_slave_get_rcu(bond);
-               rcu_read_unlock();
                if (!real_dev)
                        return -EOPNOTSUPP;
 
@@ -5382,9 +5380,7 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
        struct net_device *real_dev;
        struct phy_device *phydev;
 
-       rcu_read_lock();
        real_dev = bond_option_active_slave_get_rcu(bond);
-       rcu_read_unlock();
        if (real_dev) {
                ops = real_dev->ethtool_ops;
                phydev = real_dev->phydev;
index f6ae3a4baea40dea1e52b9424956b0e18c22c873..83cfd2d70247dbb7162e23aad3bb8c757f8959a1 100644 (file)
@@ -346,7 +346,7 @@ static inline bool bond_uses_primary(struct bonding *bond)
 
 static inline struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond)
 {
-       struct slave *slave = rcu_dereference(bond->curr_active_slave);
+       struct slave *slave = rcu_dereference_rtnl(bond->curr_active_slave);
 
        return bond_uses_primary(bond) && slave ? slave->dev : NULL;
 }