[Trusty,PATCHv2,1/2] UBUNTU: SAUCE: Backport helper function netdev_upper_get_next_dev_rcu

Message ID 20180605141540.12813-2-dan.streetman@canonical.com
State New
Headers show
Series
  • Fix kernel WARNING with bonding/vlan and LRO
Related show

Commit Message

Dan Streetman June 5, 2018, 2:15 p.m.
From: Vlad Yasevich <vyasevic@redhat.com>

BugLink: https://bugs.launchpad.net/bugs/1771480

This partial backport adds the function netdev_upper_get_next_dev_rcu()
and iterator macro netdev_for_each_upper_dev_rcu() from upstream commit:

commit 44a4085538c844e79d6ee6bcf46fabf7c57a9a38
Author: Vlad Yasevich <vyasevic@redhat.com>
Date:   Fri May 16 17:20:38 2014 -0400

    bonding: Fix stacked device detection in arp monitoring

These are used in the next patch in this series.  The rest of the changes
from the upstream commit are not included in this backport.

(backported from 44a4085538c844e79d6ee6bcf46fabf7c57a9a38)
Signed-off-by: Dan Streetman <ddstreet@canonical.com>
---
 include/linux/netdevice.h |  9 +++++++++
 net/core/dev.c            | 26 ++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

Patch

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 21ced47b9664..6e56f3af821c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2927,9 +2927,18 @@  extern int		bpf_jit_enable;
 
 bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev);
 bool netdev_has_any_upper_dev(struct net_device *dev);
+struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
+						     struct list_head **iter);
 struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 						     struct list_head **iter);
 
+/* iterate through upper list, must be called under RCU read lock */
+#define netdev_for_each_upper_dev_rcu(dev, updev, iter) \
+	for (iter = &(dev)->adj_list.upper, \
+	     updev = netdev_upper_get_next_dev_rcu(dev, &(iter)); \
+	     updev; \
+	     updev = netdev_upper_get_next_dev_rcu(dev, &(iter)))
+
 /* iterate through upper list, must be called under RCU read lock */
 #define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \
 	for (iter = &(dev)->all_adj_list.upper, \
diff --git a/net/core/dev.c b/net/core/dev.c
index 1d37e93ad23c..efb8f8f39863 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4538,6 +4538,32 @@  void *netdev_adjacent_get_private(struct list_head *adj_list)
 }
 EXPORT_SYMBOL(netdev_adjacent_get_private);
 
+/**
+ * netdev_upper_get_next_dev_rcu - Get the next dev from upper list
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next device from the dev's upper list, starting from iter
+ * position. The caller must hold RCU read lock.
+ */
+struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
+						 struct list_head **iter)
+{
+	struct netdev_adjacent *upper;
+
+	WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
+
+	upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
+
+	if (&upper->list == &dev->adj_list.upper)
+		return NULL;
+
+	*iter = &upper->list;
+
+	return upper->dev;
+}
+EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+
 /**
  * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
  * @dev: device