diff options
author | Sabrina Dubroca <sd@queasysnail.net> | 2016-08-12 10:10:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-13 18:15:54 -0400 |
commit | 952fcfd08c8109951622579d0ae7b9cd6cafd688 (patch) | |
tree | 16e787138d3da28899e3a0028962928c79a4af07 | |
parent | e20038724552cd05e351cd7d7526d646953d26b7 (diff) |
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>
-rw-r--r-- | drivers/net/macsec.c | 2 | ||||
-rw-r--r-- | drivers/net/macvlan.c | 2 | ||||
-rw-r--r-- | include/linux/netdevice.h | 3 | ||||
-rw-r--r-- | net/8021q/vlan.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 10 |
5 files changed, 7 insertions, 12 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 2043e8c97a81..351e701eb043 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c | |||
@@ -3201,7 +3201,7 @@ static int macsec_newlink(struct net *net, struct net_device *dev, | |||
3201 | 3201 | ||
3202 | dev_hold(real_dev); | 3202 | dev_hold(real_dev); |
3203 | 3203 | ||
3204 | macsec->nest_level = dev_get_nest_level(real_dev, netif_is_macsec) + 1; | 3204 | macsec->nest_level = dev_get_nest_level(real_dev) + 1; |
3205 | netdev_lockdep_set_classes(dev); | 3205 | netdev_lockdep_set_classes(dev); |
3206 | lockdep_set_class_and_subclass(&dev->addr_list_lock, | 3206 | lockdep_set_class_and_subclass(&dev->addr_list_lock, |
3207 | &macsec_netdev_addr_lock_key, | 3207 | &macsec_netdev_addr_lock_key, |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index cd9b53834bf6..3234fcdea317 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -1315,7 +1315,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
1315 | vlan->dev = dev; | 1315 | vlan->dev = dev; |
1316 | vlan->port = port; | 1316 | vlan->port = port; |
1317 | vlan->set_features = MACVLAN_FEATURES; | 1317 | vlan->set_features = MACVLAN_FEATURES; |
1318 | vlan->nest_level = dev_get_nest_level(lowerdev, netif_is_macvlan) + 1; | 1318 | vlan->nest_level = dev_get_nest_level(lowerdev) + 1; |
1319 | 1319 | ||
1320 | vlan->mode = MACVLAN_MODE_VEPA; | 1320 | vlan->mode = MACVLAN_MODE_VEPA; |
1321 | if (data && data[IFLA_MACVLAN_MODE]) | 1321 | if (data && data[IFLA_MACVLAN_MODE]) |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 076df5360ba5..3a788bf0affd 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -3891,8 +3891,7 @@ void netdev_default_l2upper_neigh_destroy(struct net_device *dev, | |||
3891 | extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly; | 3891 | extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly; |
3892 | void netdev_rss_key_fill(void *buffer, size_t len); | 3892 | void netdev_rss_key_fill(void *buffer, size_t len); |
3893 | 3893 | ||
3894 | int dev_get_nest_level(struct net_device *dev, | 3894 | int dev_get_nest_level(struct net_device *dev); |
3895 | bool (*type_check)(const struct net_device *dev)); | ||
3896 | int skb_checksum_help(struct sk_buff *skb); | 3895 | int skb_checksum_help(struct sk_buff *skb); |
3897 | struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | 3896 | struct sk_buff *__skb_gso_segment(struct sk_buff *skb, |
3898 | netdev_features_t features, bool tx_path); | 3897 | netdev_features_t features, bool tx_path); |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 82a116ba590e..8de138d3306b 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -169,7 +169,7 @@ int register_vlan_dev(struct net_device *dev) | |||
169 | if (err < 0) | 169 | if (err < 0) |
170 | goto out_uninit_mvrp; | 170 | goto out_uninit_mvrp; |
171 | 171 | ||
172 | vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1; | 172 | vlan->nest_level = dev_get_nest_level(real_dev) + 1; |
173 | err = register_netdevice(dev); | 173 | err = register_netdevice(dev); |
174 | if (err < 0) | 174 | if (err < 0) |
175 | goto out_uninit_mvrp; | 175 | goto out_uninit_mvrp; |
diff --git a/net/core/dev.c b/net/core/dev.c index 4ce07dc25573..dd6ce598de89 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -6045,8 +6045,7 @@ void *netdev_lower_dev_get_private(struct net_device *dev, | |||
6045 | EXPORT_SYMBOL(netdev_lower_dev_get_private); | 6045 | EXPORT_SYMBOL(netdev_lower_dev_get_private); |
6046 | 6046 | ||
6047 | 6047 | ||
6048 | int dev_get_nest_level(struct net_device *dev, | 6048 | int dev_get_nest_level(struct net_device *dev) |
6049 | bool (*type_check)(const struct net_device *dev)) | ||
6050 | { | 6049 | { |
6051 | struct net_device *lower = NULL; | 6050 | struct net_device *lower = NULL; |
6052 | struct list_head *iter; | 6051 | struct list_head *iter; |
@@ -6056,15 +6055,12 @@ int dev_get_nest_level(struct net_device *dev, | |||
6056 | ASSERT_RTNL(); | 6055 | ASSERT_RTNL(); |
6057 | 6056 | ||
6058 | netdev_for_each_lower_dev(dev, lower, iter) { | 6057 | netdev_for_each_lower_dev(dev, lower, iter) { |
6059 | nest = dev_get_nest_level(lower, type_check); | 6058 | nest = dev_get_nest_level(lower); |
6060 | if (max_nest < nest) | 6059 | if (max_nest < nest) |
6061 | max_nest = nest; | 6060 | max_nest = nest; |
6062 | } | 6061 | } |
6063 | 6062 | ||
6064 | if (type_check(dev)) | 6063 | return max_nest + 1; |
6065 | max_nest++; | ||
6066 | |||
6067 | return max_nest; | ||
6068 | } | 6064 | } |
6069 | EXPORT_SYMBOL(dev_get_nest_level); | 6065 | EXPORT_SYMBOL(dev_get_nest_level); |
6070 | 6066 | ||