Message ID | 1400260697-32601-2-git-send-email-vyasevic@redhat.com |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
On Fri, 2014-05-16 at 13:18 -0400, Vlad Yasevich wrote: > Multiple devices in the kernel can be stacked/nested and they > need to know their nesting level for the purposes of lockdep. > This patch provides a generic function that determines a nesting > level of a particular device by its type (ex: vlan, macvlan, etc). > We only care about nesting of the same type of devices. > > For example: > eth0 <- vlan0.10 <- macvlan0 <- vlan1.20 > > The nesting level of vlan1.20 would be 1, since there is another vlan > in the stack under it. > > Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> > --- > include/linux/netdevice.h | 10 ++++++++++ > net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 58 insertions(+) Nice, but if LOCKDEP is not used, do we really want to have dev_get_nest_level() being something else than a constant ? -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 05/16/2014 01:32 PM, Eric Dumazet wrote: > On Fri, 2014-05-16 at 13:18 -0400, Vlad Yasevich wrote: >> Multiple devices in the kernel can be stacked/nested and they >> need to know their nesting level for the purposes of lockdep. >> This patch provides a generic function that determines a nesting >> level of a particular device by its type (ex: vlan, macvlan, etc). >> We only care about nesting of the same type of devices. >> >> For example: >> eth0 <- vlan0.10 <- macvlan0 <- vlan1.20 >> >> The nesting level of vlan1.20 would be 1, since there is another vlan >> in the stack under it. >> >> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> >> --- >> include/linux/netdevice.h | 10 ++++++++++ >> net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 58 insertions(+) > > Nice, but if LOCKDEP is not used, do we really want to have > dev_get_nest_level() being something else than a constant ? > > Doesn't seem to hurt. As it stands right now, vlan code will keep calculating its own every time it needs to take a lock and it will be other then 1 when you have a stack of them. -vlad -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 20e99ef..e32d313 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3077,6 +3077,14 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, priv; \ priv = netdev_lower_get_next_private_rcu(dev, &(iter))) +void *netdev_lower_get_next_rcu(struct net_device *dev, + struct list_head **iter); +#define netdev_for_each_lower_dev_rcu(dev, priv, iter) \ + for (iter = &(dev)->adj_list.lower, \ + priv = netdev_lower_get_next_rcu(dev, &(iter)); \ + priv; \ + priv = netdev_lower_get_next_rcu(dev, &(iter))) + void *netdev_adjacent_get_private(struct list_head *adj_list); void *netdev_lower_get_first_private_rcu(struct net_device *dev); struct net_device *netdev_master_upper_dev_get(struct net_device *dev); @@ -3092,6 +3100,8 @@ void netdev_upper_dev_unlink(struct net_device *dev, void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); void *netdev_lower_dev_get_private(struct net_device *dev, struct net_device *lower_dev); +int dev_get_nest_level(struct net_device *dev, + bool (*type_check)(struct net_device *dev)); int skb_checksum_help(struct sk_buff *skb); struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path); diff --git a/net/core/dev.c b/net/core/dev.c index 6da649b..9f7c2c2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4622,6 +4622,32 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); /** + * netdev_lower_get_next_rcu - Get the next device from the lower neighbour + * list, RCU variant + * @dev: device + * @iter: list_head ** of the current position + * + * Gets the next netdev_adjacent from the dev's lower neighbour + * list, starting from iter position. The caller must hold RCU read lock. + */ +void *netdev_lower_get_next_rcu(struct net_device *dev, struct list_head **iter) +{ + struct netdev_adjacent *lower; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); + + if (&lower->list == &dev->adj_list.lower) + return NULL; + + *iter = &lower->list; + + return lower->dev; +} +EXPORT_SYMBOL(netdev_lower_get_next_rcu); + +/** * netdev_lower_get_first_private_rcu - Get the first ->private from the * lower neighbour list, RCU * variant @@ -5071,6 +5097,28 @@ void *netdev_lower_dev_get_private(struct net_device *dev, } EXPORT_SYMBOL(netdev_lower_dev_get_private); + +int dev_get_nest_level(struct net_device *dev, + bool (*type_check)(struct net_device *dev)) +{ + struct net_device *lower = NULL; + struct list_head *iter; + int max_nest = -1; + int nest; + + netdev_for_each_lower_dev_rcu(dev, lower, iter) { + nest = dev_get_nest_level(lower, type_check); + if (max_nest < nest) + max_nest = nest; + } + + if (type_check(dev)) + max_nest++; + + return max_nest; +} +EXPORT_SYMBOL(dev_get_nest_level); + static void dev_change_rx_flags(struct net_device *dev, int flags) { const struct net_device_ops *ops = dev->netdev_ops;
Multiple devices in the kernel can be stacked/nested and they need to know their nesting level for the purposes of lockdep. This patch provides a generic function that determines a nesting level of a particular device by its type (ex: vlan, macvlan, etc). We only care about nesting of the same type of devices. For example: eth0 <- vlan0.10 <- macvlan0 <- vlan1.20 The nesting level of vlan1.20 would be 1, since there is another vlan in the stack under it. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> --- include/linux/netdevice.h | 10 ++++++++++ net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+)