net: remove type_check from dev_get_nest_level()
The idea for type_check in dev_get_nest_level() was to count the number of nested devices of the same type (currently, only macvlan or vlan devices). This prevented the false positive lockdep warning on configurations such as: eth0 <--- macvlan0 <--- vlan0 <--- macvlan1 However, this doesn't prevent a warning on a configuration such as: eth0 <--- macvlan0 <--- vlan0 eth1 <--- vlan1 <--- macvlan1 In this case, all the locks end up with a nesting subclass of 1, so lockdep thinks that there is still a deadlock: - in the first case we have (macvlan_netdev_addr_lock_key, 1) and then take (vlan_netdev_xmit_lock_key, 1) - in the second case, we have (vlan_netdev_xmit_lock_key, 1) and then take (macvlan_netdev_addr_lock_key, 1) By removing the linktype check in dev_get_nest_level() and always incrementing the nesting depth, lockdep considers this configuration valid. Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e200387245
commit
952fcfd08c
|
@ -3201,7 +3201,7 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
|
||||||
|
|
||||||
dev_hold(real_dev);
|
dev_hold(real_dev);
|
||||||
|
|
||||||
macsec->nest_level = dev_get_nest_level(real_dev, netif_is_macsec) + 1;
|
macsec->nest_level = dev_get_nest_level(real_dev) + 1;
|
||||||
netdev_lockdep_set_classes(dev);
|
netdev_lockdep_set_classes(dev);
|
||||||
lockdep_set_class_and_subclass(&dev->addr_list_lock,
|
lockdep_set_class_and_subclass(&dev->addr_list_lock,
|
||||||
&macsec_netdev_addr_lock_key,
|
&macsec_netdev_addr_lock_key,
|
||||||
|
|
|
@ -1315,7 +1315,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
||||||
vlan->dev = dev;
|
vlan->dev = dev;
|
||||||
vlan->port = port;
|
vlan->port = port;
|
||||||
vlan->set_features = MACVLAN_FEATURES;
|
vlan->set_features = MACVLAN_FEATURES;
|
||||||
vlan->nest_level = dev_get_nest_level(lowerdev, netif_is_macvlan) + 1;
|
vlan->nest_level = dev_get_nest_level(lowerdev) + 1;
|
||||||
|
|
||||||
vlan->mode = MACVLAN_MODE_VEPA;
|
vlan->mode = MACVLAN_MODE_VEPA;
|
||||||
if (data && data[IFLA_MACVLAN_MODE])
|
if (data && data[IFLA_MACVLAN_MODE])
|
||||||
|
|
|
@ -3891,8 +3891,7 @@ void netdev_default_l2upper_neigh_destroy(struct net_device *dev,
|
||||||
extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly;
|
extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly;
|
||||||
void netdev_rss_key_fill(void *buffer, size_t len);
|
void netdev_rss_key_fill(void *buffer, size_t len);
|
||||||
|
|
||||||
int dev_get_nest_level(struct net_device *dev,
|
int dev_get_nest_level(struct net_device *dev);
|
||||||
bool (*type_check)(const struct net_device *dev));
|
|
||||||
int skb_checksum_help(struct sk_buff *skb);
|
int skb_checksum_help(struct sk_buff *skb);
|
||||||
struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
|
struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
|
||||||
netdev_features_t features, bool tx_path);
|
netdev_features_t features, bool tx_path);
|
||||||
|
|
|
@ -169,7 +169,7 @@ int register_vlan_dev(struct net_device *dev)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_uninit_mvrp;
|
goto out_uninit_mvrp;
|
||||||
|
|
||||||
vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1;
|
vlan->nest_level = dev_get_nest_level(real_dev) + 1;
|
||||||
err = register_netdevice(dev);
|
err = register_netdevice(dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_uninit_mvrp;
|
goto out_uninit_mvrp;
|
||||||
|
|
|
@ -6045,8 +6045,7 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
|
||||||
EXPORT_SYMBOL(netdev_lower_dev_get_private);
|
EXPORT_SYMBOL(netdev_lower_dev_get_private);
|
||||||
|
|
||||||
|
|
||||||
int dev_get_nest_level(struct net_device *dev,
|
int dev_get_nest_level(struct net_device *dev)
|
||||||
bool (*type_check)(const struct net_device *dev))
|
|
||||||
{
|
{
|
||||||
struct net_device *lower = NULL;
|
struct net_device *lower = NULL;
|
||||||
struct list_head *iter;
|
struct list_head *iter;
|
||||||
|
@ -6056,15 +6055,12 @@ int dev_get_nest_level(struct net_device *dev,
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
netdev_for_each_lower_dev(dev, lower, iter) {
|
netdev_for_each_lower_dev(dev, lower, iter) {
|
||||||
nest = dev_get_nest_level(lower, type_check);
|
nest = dev_get_nest_level(lower);
|
||||||
if (max_nest < nest)
|
if (max_nest < nest)
|
||||||
max_nest = nest;
|
max_nest = nest;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_check(dev))
|
return max_nest + 1;
|
||||||
max_nest++;
|
|
||||||
|
|
||||||
return max_nest;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dev_get_nest_level);
|
EXPORT_SYMBOL(dev_get_nest_level);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue