Merge branch 'bonding-fix-bonding-interface-bugs'
Taehee Yoo says: ==================== bonding: fix bonding interface bugs This patchset fixes lockdep problem in bonding interface 1. The first patch is to add missing netdev_update_lockdep_key(). After bond_release(), netdev_update_lockdep_key() should be called. But both ioctl path and attribute path don't call netdev_update_lockdep_key(). This patch adds missing netdev_update_lockdep_key(). 2. The second patch is to export netdev_next_lower_dev_rcu symbol. netdev_next_lower_dev_rcu() is useful to implement the function, which is to walk their all lower interfaces. This patch is actually a preparing patch for the third patch. 3. The last patch is to fix lockdep waring in bond_get_stats(). The stats_lock uses a dynamic lockdep key. So, after "nomaster" operation, updating the dynamic lockdep key routine is needed. but it doesn't So, lockdep warning occurs. Change log: v1 -> v2: - Update headline from "fix bonding interface bugs" to "bonding: fix bonding interface bugs" - Drop a patch("bonding: do not collect slave's stats") - Add new patches - ("net: export netdev_next_lower_dev_rcu()") - ("bonding: fix lockdep warning in bond_get_stats()") ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c230978fb7
@ -3526,6 +3526,47 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
static int bond_get_lowest_level_rcu(struct net_device *dev)
|
||||
{
|
||||
struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
|
||||
struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
|
||||
int cur = 0, max = 0;
|
||||
|
||||
now = dev;
|
||||
iter = &dev->adj_list.lower;
|
||||
|
||||
while (1) {
|
||||
next = NULL;
|
||||
while (1) {
|
||||
ldev = netdev_next_lower_dev_rcu(now, &iter);
|
||||
if (!ldev)
|
||||
break;
|
||||
|
||||
next = ldev;
|
||||
niter = &ldev->adj_list.lower;
|
||||
dev_stack[cur] = now;
|
||||
iter_stack[cur++] = iter;
|
||||
if (max <= cur)
|
||||
max = cur;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!next) {
|
||||
if (!cur)
|
||||
return max;
|
||||
next = dev_stack[--cur];
|
||||
niter = iter_stack[cur];
|
||||
}
|
||||
|
||||
now = next;
|
||||
iter = niter;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bond_get_stats(struct net_device *bond_dev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
@ -3533,11 +3574,17 @@ static void bond_get_stats(struct net_device *bond_dev,
|
||||
struct rtnl_link_stats64 temp;
|
||||
struct list_head *iter;
|
||||
struct slave *slave;
|
||||
int nest_level = 0;
|
||||
|
||||
spin_lock(&bond->stats_lock);
|
||||
memcpy(stats, &bond->bond_stats, sizeof(*stats));
|
||||
|
||||
rcu_read_lock();
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
nest_level = bond_get_lowest_level_rcu(bond_dev);
|
||||
#endif
|
||||
|
||||
spin_lock_nested(&bond->stats_lock, nest_level);
|
||||
memcpy(stats, &bond->bond_stats, sizeof(*stats));
|
||||
|
||||
bond_for_each_slave_rcu(bond, slave, iter) {
|
||||
const struct rtnl_link_stats64 *new =
|
||||
dev_get_stats(slave->dev, &temp);
|
||||
@ -3547,10 +3594,10 @@ static void bond_get_stats(struct net_device *bond_dev,
|
||||
/* save off the slave stats for the next run */
|
||||
memcpy(&slave->slave_stats, new, sizeof(*new));
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
memcpy(&bond->bond_stats, stats, sizeof(*stats));
|
||||
spin_unlock(&bond->stats_lock);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
|
||||
@ -3640,6 +3687,8 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
|
||||
case BOND_RELEASE_OLD:
|
||||
case SIOCBONDRELEASE:
|
||||
res = bond_release(bond_dev, slave_dev);
|
||||
if (!res)
|
||||
netdev_update_lockdep_key(slave_dev);
|
||||
break;
|
||||
case BOND_SETHWADDR_OLD:
|
||||
case SIOCBONDSETHWADDR:
|
||||
|
@ -1398,6 +1398,8 @@ static int bond_option_slaves_set(struct bonding *bond,
|
||||
case '-':
|
||||
slave_dbg(bond->dev, dev, "Releasing interface\n");
|
||||
ret = bond_release(bond->dev, dev);
|
||||
if (!ret)
|
||||
netdev_update_lockdep_key(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -72,6 +72,8 @@ void netdev_set_default_ethtool_ops(struct net_device *dev,
|
||||
#define NET_RX_SUCCESS 0 /* keep 'em coming, baby */
|
||||
#define NET_RX_DROP 1 /* packet dropped */
|
||||
|
||||
#define MAX_NEST_DEV 8
|
||||
|
||||
/*
|
||||
* Transmit return codes: transmit return codes originate from three different
|
||||
* namespaces:
|
||||
@ -4389,11 +4391,8 @@ void *netdev_lower_get_next(struct net_device *dev,
|
||||
ldev; \
|
||||
ldev = netdev_lower_get_next(dev, &(iter)))
|
||||
|
||||
struct net_device *netdev_all_lower_get_next(struct net_device *dev,
|
||||
struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
|
||||
struct list_head **iter);
|
||||
struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
|
||||
struct list_head **iter);
|
||||
|
||||
int netdev_walk_all_lower_dev(struct net_device *dev,
|
||||
int (*fn)(struct net_device *lower_dev,
|
||||
void *data),
|
||||
|
@ -146,7 +146,6 @@
|
||||
#include "net-sysfs.h"
|
||||
|
||||
#define MAX_GRO_SKBS 8
|
||||
#define MAX_NEST_DEV 8
|
||||
|
||||
/* This should be increased if a protocol with a bigger head is added. */
|
||||
#define GRO_MAX_HEAD (MAX_HEADER + 128)
|
||||
@ -7207,8 +7206,8 @@ static int __netdev_walk_all_lower_dev(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
|
||||
struct list_head **iter)
|
||||
struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
|
||||
struct list_head **iter)
|
||||
{
|
||||
struct netdev_adjacent *lower;
|
||||
|
||||
@ -7220,6 +7219,7 @@ static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
|
||||
|
||||
return lower->dev;
|
||||
}
|
||||
EXPORT_SYMBOL(netdev_next_lower_dev_rcu);
|
||||
|
||||
static u8 __netdev_upper_depth(struct net_device *dev)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user