* [PATCH v5 net-next 07/27] net: add for_each iterators through neighbour lower link's private
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev
Cc: jiri, Veaceslav Falico, David S. Miller, Eric Dumazet,
Alexander Duyck
In-Reply-To: <1380093632-1842-1-git-send-email-vfalico@redhat.com>
Add a possibility to iterate through netdev_adjacent's private, currently
only for lower neighbours.
Add both RCU and RTNL/other locking variants of iterators, and make the
non-rcu variant to be safe from removal.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v4 -> v5
No change.
v3 -> v4:
Make netdev_for_each_lower_private() be safe for the entry removal, by
storing the ->next pointer in iter.
v2 -> v3:
No change.
v1 -> v2:
No changes.
RFC -> v1:
rename neighbour_dev_list/all_dev_list to adj_list/all_adj_list and rework
the naming of functions - to make the use the pattern
netdev_(all_)(lower|upper)_* . Also reword the commit message - I had to
read it three times to understand :-/, and move it closer to the beginning
of the patchset.
include/linux/netdevice.h | 17 ++++++++++++++
net/core/dev.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 75d5bea..168974e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2833,6 +2833,23 @@ extern struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *d
updev; \
updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)))
+extern void *netdev_lower_get_next_private(struct net_device *dev,
+ struct list_head **iter);
+extern void *netdev_lower_get_next_private_rcu(struct net_device *dev,
+ struct list_head **iter);
+
+#define netdev_for_each_lower_private(dev, priv, iter) \
+ for (iter = (dev)->adj_list.lower.next, \
+ priv = netdev_lower_get_next_private(dev, &(iter)); \
+ priv; \
+ priv = netdev_lower_get_next_private(dev, &(iter)))
+
+#define netdev_for_each_lower_private_rcu(dev, priv, iter) \
+ for (iter = &(dev)->adj_list.lower, \
+ priv = netdev_lower_get_next_private_rcu(dev, &(iter)); \
+ priv; \
+ priv = netdev_lower_get_next_private_rcu(dev, &(iter)))
+
extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
extern int netdev_upper_dev_link(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index c69ab74..0aa844a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4466,7 +4466,8 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
-/* netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
+/**
+ * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
* @dev: device
* @iter: list_head ** of the current position
*
@@ -4492,6 +4493,63 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu);
/**
+ * netdev_lower_get_next_private - Get the next ->private from the
+ * lower neighbour list
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next netdev_adjacent->private from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold either hold the
+ * RTNL lock or its own locking that guarantees that the neighbour lower
+ * list will remain unchainged.
+ */
+void *netdev_lower_get_next_private(struct net_device *dev,
+ struct list_head **iter)
+{
+ struct netdev_adjacent *lower;
+
+ lower = list_entry(*iter, struct netdev_adjacent, list);
+
+ if (&lower->list == &dev->adj_list.lower)
+ return NULL;
+
+ if (iter)
+ *iter = lower->list.next;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_get_next_private);
+
+/**
+ * netdev_lower_get_next_private_rcu - Get the next ->private from the
+ * lower neighbour list, RCU
+ * variant
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next netdev_adjacent->private from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold RCU read lock.
+ */
+void *netdev_lower_get_next_private_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;
+
+ if (iter)
+ *iter = &lower->list;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_get_next_private_rcu);
+
+/**
* netdev_master_upper_dev_get_rcu - Get master upper device
* @dev: device
*
--
1.8.4
^ permalink raw reply related
* [PATCH v5 net-next 05/27] bonding: populate neighbour's private on enslave
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev; +Cc: jiri, Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1380093632-1842-1-git-send-email-vfalico@redhat.com>
Use the new provided function when attaching the lower slave to populate
its ->private with struct slave *new_slave. Also, move it to the end to
be able to 'find' it only after it was completely initialized, and
deinitialize in the first place on release.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v4 -> v5
No change.
v3 -> v4:
No change.
v2 -> v3:
No change.
v1 -> v2:
No changes.
RFC -> v1:
Move the patch right after the introduction of ->private, to immediately
use it - easier for review and more logical.
drivers/net/bonding/bond_main.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 91c4ab8..8e41416 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1233,11 +1233,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
}
static int bond_master_upper_dev_link(struct net_device *bond_dev,
- struct net_device *slave_dev)
+ struct net_device *slave_dev,
+ struct slave *slave)
{
int err;
- err = netdev_master_upper_dev_link(slave_dev, bond_dev);
+ err = netdev_master_upper_dev_link_private(slave_dev, bond_dev, slave);
if (err)
return err;
slave_dev->flags |= IFF_SLAVE;
@@ -1413,17 +1414,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
}
}
- res = bond_master_upper_dev_link(bond_dev, slave_dev);
- if (res) {
- pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
- goto err_restore_mac;
- }
-
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
pr_debug("Opening slave %s failed\n", slave_dev->name);
- goto err_unset_master;
+ goto err_restore_mac;
}
new_slave->bond = bond;
@@ -1637,6 +1632,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_dest_symlinks;
}
+ res = bond_master_upper_dev_link(bond_dev, slave_dev, new_slave);
+ if (res) {
+ pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
+ goto err_unregister;
+ }
+
+
pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
bond_dev->name, slave_dev->name,
bond_is_active_slave(new_slave) ? "n active" : " backup",
@@ -1646,6 +1648,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
return 0;
/* Undo stages on error */
+err_unregister:
+ netdev_rx_handler_unregister(slave_dev);
+
err_dest_symlinks:
bond_destroy_slave_symlinks(bond_dev, slave_dev);
@@ -1675,9 +1680,6 @@ err_close:
slave_dev->priv_flags &= ~IFF_BONDING;
dev_close(slave_dev);
-err_unset_master:
- bond_upper_dev_unlink(bond_dev, slave_dev);
-
err_restore_mac:
if (!bond->params.fail_over_mac) {
/* XXX TODO - fom follow mode needs to change master's
@@ -1748,6 +1750,8 @@ static int __bond_release_one(struct net_device *bond_dev,
}
write_unlock_bh(&bond->lock);
+
+ bond_upper_dev_unlink(bond_dev, slave_dev);
/* unregister rx_handler early so bond_handle_frame wouldn't be called
* for this slave anymore.
*/
@@ -1866,8 +1870,6 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_hw_addr_flush(bond_dev, slave_dev);
}
- bond_upper_dev_unlink(bond_dev, slave_dev);
-
slave_disable_netpoll(slave);
/* close slave before restoring its mac address */
--
1.8.4
^ permalink raw reply related
* [PATCH v5 net-next 06/27] bonding: modify bond_get_slave_by_dev() to use neighbours
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev; +Cc: jiri, Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1380093632-1842-1-git-send-email-vfalico@redhat.com>
It should be used under rtnl/bonding lock, so use the non-RCU version.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v4 -> v5:
Removed casting of NULL pointer.
v3 -> v4:
No change.
v2 -> v3:
No change.
v1 -> v2:
No changes.
RFC -> v1:
Move the patch right after we've populated ->private with bonding.
drivers/net/bonding/bonding.h | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 03cf3fd..90f4847 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -276,13 +276,7 @@ struct bonding {
static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
struct net_device *slave_dev)
{
- struct slave *slave = NULL;
-
- bond_for_each_slave(bond, slave)
- if (slave->dev == slave_dev)
- return slave;
-
- return NULL;
+ return netdev_lower_dev_get_private(bond->dev, slave_dev);
}
static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
--
1.8.4
^ permalink raw reply related
* [PATCH v5 net-next 04/27] net: add netdev_adjacent->private and allow to use it
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev
Cc: jiri, Veaceslav Falico, David S. Miller, Eric Dumazet,
Alexander Duyck
In-Reply-To: <1380093632-1842-1-git-send-email-vfalico@redhat.com>
Currently, even though we can access any linked device, we can't attach
anything to it, which is vital to properly manage them.
To fix this, add a new void *private to netdev_adjacent and functions
setting/getting it (per link), so that we can save, per example, bonding's
slave structures there, per slave device.
netdev_master_upper_dev_link_private(dev, upper_dev, private) links dev to
upper dev and populates the neighbour link only with private.
netdev_lower_dev_get_private{,_rcu}() returns the private, if found.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v4 -> v5
No change.
v3 -> v4:
No change.
v2 -> v3:
No change.
v1 -> v2:
No changes.
RFC -> v1:
rename neighbour_dev_list/all_dev_list to adj_list/all_adj_list and rework
the naming of functions - to make the use the pattern
netdev_(all_)(lower|upper)_* .
include/linux/netdevice.h | 7 +++++
net/core/dev.c | 68 +++++++++++++++++++++++++++++++++++++++--------
2 files changed, 64 insertions(+), 11 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 514045c..75d5bea 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2839,8 +2839,15 @@ extern int netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev);
extern int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev);
+extern int netdev_master_upper_dev_link_private(struct net_device *dev,
+ struct net_device *upper_dev,
+ void *private);
extern void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev);
+extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
+ struct net_device *lower_dev);
+extern void *netdev_lower_dev_get_private(struct net_device *dev,
+ struct net_device *lower_dev);
extern int skb_checksum_help(struct sk_buff *skb);
extern 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 9290f09..c69ab74 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4376,6 +4376,9 @@ struct netdev_adjacent {
/* counter for the number of times this device was added to us */
u16 ref_nr;
+ /* private field for the users */
+ void *private;
+
struct list_head list;
struct rcu_head rcu;
};
@@ -4510,7 +4513,7 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
static int __netdev_adjacent_dev_insert(struct net_device *dev,
struct net_device *adj_dev,
struct list_head *dev_list,
- bool master)
+ void *private, bool master)
{
struct netdev_adjacent *adj;
@@ -4528,6 +4531,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->dev = adj_dev;
adj->master = master;
adj->ref_nr = 1;
+ adj->private = private;
dev_hold(adj_dev);
pr_debug("dev_hold for %s, because of link added from %s to %s\n",
@@ -4574,15 +4578,17 @@ int __netdev_adjacent_dev_link_lists(struct net_device *dev,
struct net_device *upper_dev,
struct list_head *up_list,
struct list_head *down_list,
- bool master)
+ void *private, bool master)
{
int ret;
- ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, master);
+ ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private,
+ master);
if (ret)
return ret;
- ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, false);
+ ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private,
+ false);
if (ret) {
__netdev_adjacent_dev_remove(dev, upper_dev, up_list);
return ret;
@@ -4597,7 +4603,7 @@ int __netdev_adjacent_dev_link(struct net_device *dev,
return __netdev_adjacent_dev_link_lists(dev, upper_dev,
&dev->all_adj_list.upper,
&upper_dev->all_adj_list.lower,
- false);
+ NULL, false);
}
void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
@@ -4619,7 +4625,7 @@ void __netdev_adjacent_dev_unlink(struct net_device *dev,
int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
struct net_device *upper_dev,
- bool master)
+ void *private, bool master)
{
int ret = __netdev_adjacent_dev_link(dev, upper_dev);
@@ -4629,7 +4635,7 @@ int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
ret = __netdev_adjacent_dev_link_lists(dev, upper_dev,
&dev->adj_list.upper,
&upper_dev->adj_list.lower,
- master);
+ private, master);
if (ret) {
__netdev_adjacent_dev_unlink(dev, upper_dev);
return ret;
@@ -4648,7 +4654,8 @@ void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
}
static int __netdev_upper_dev_link(struct net_device *dev,
- struct net_device *upper_dev, bool master)
+ struct net_device *upper_dev, bool master,
+ void *private)
{
struct netdev_adjacent *i, *j, *to_i, *to_j;
int ret = 0;
@@ -4668,7 +4675,8 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (master && netdev_master_upper_dev_get(dev))
return -EBUSY;
- ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master);
+ ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private,
+ master);
if (ret)
return ret;
@@ -4759,7 +4767,7 @@ rollback_mesh:
int netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, false);
+ return __netdev_upper_dev_link(dev, upper_dev, false, NULL);
}
EXPORT_SYMBOL(netdev_upper_dev_link);
@@ -4777,10 +4785,18 @@ EXPORT_SYMBOL(netdev_upper_dev_link);
int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, true);
+ return __netdev_upper_dev_link(dev, upper_dev, true, NULL);
}
EXPORT_SYMBOL(netdev_master_upper_dev_link);
+int netdev_master_upper_dev_link_private(struct net_device *dev,
+ struct net_device *upper_dev,
+ void *private)
+{
+ return __netdev_upper_dev_link(dev, upper_dev, true, private);
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_link_private);
+
/**
* netdev_upper_dev_unlink - Removes a link to upper device
* @dev: device
@@ -4818,6 +4834,36 @@ void netdev_upper_dev_unlink(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
+void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
+ struct net_device *lower_dev)
+{
+ struct netdev_adjacent *lower;
+
+ if (!lower_dev)
+ return NULL;
+ lower = __netdev_find_adj_rcu(dev, lower_dev, &dev->adj_list.lower);
+ if (!lower)
+ return NULL;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu);
+
+void *netdev_lower_dev_get_private(struct net_device *dev,
+ struct net_device *lower_dev)
+{
+ struct netdev_adjacent *lower;
+
+ if (!lower_dev)
+ return NULL;
+ lower = __netdev_find_adj(dev, lower_dev, &dev->adj_list.lower);
+ if (!lower)
+ return NULL;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_dev_get_private);
+
static void dev_change_rx_flags(struct net_device *dev, int flags)
{
const struct net_device_ops *ops = dev->netdev_ops;
--
1.8.4
^ permalink raw reply related
* [PATCH v5 net-next 03/27] net: add RCU variant to search for netdev_adjacent link
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev
Cc: jiri, Veaceslav Falico, David S. Miller, Eric Dumazet,
Alexander Duyck, Cong Wang
In-Reply-To: <1380093632-1842-1-git-send-email-vfalico@redhat.com>
Currently we have only the RTNL flavour, however we can traverse it while
holding only RCU, so add the RCU search. Add an RCU variant that uses
list_head * as an argument, so that it can be universally used afterwards.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v4 -> v5
No change.
v3 -> v4:
Use the list argument, instead of bool upper.
v2 -> v3:
No change.
v1 -> v2:
No changes.
RFC -> v1:
rename neighbour_dev_list/all_dev_list to adj_list/all_adj_list and rework
the naming of functions - to make the use the pattern
netdev_(all_)(lower|upper)_* . Uninline functions to get better stack
traces - inline doesn't give much speed improvement, but this way the stack
traces are meaningful. Remove the unused (through the whole patchset)
functions - they can easily be added afterwards.
net/core/dev.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/net/core/dev.c b/net/core/dev.c
index 9a395e0..9290f09 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4380,6 +4380,19 @@ struct netdev_adjacent {
struct rcu_head rcu;
};
+static struct netdev_adjacent *__netdev_find_adj_rcu(struct net_device *dev,
+ struct net_device *adj_dev,
+ struct list_head *adj_list)
+{
+ struct netdev_adjacent *adj;
+
+ list_for_each_entry_rcu(adj, adj_list, list) {
+ if (adj->dev == adj_dev)
+ return adj;
+ }
+ return NULL;
+}
+
static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
struct net_device *adj_dev,
struct list_head *adj_list)
--
1.8.4
^ permalink raw reply related
* [PATCH v5 net-next 00/27] bonding: use neighbours instead of own lists
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev
Cc: jiri, Jay Vosburgh, Andy Gospodarek, Dimitris Michailidis,
David S. Miller, Patrick McHardy, Eric Dumazet, Alexander Duyck,
Veaceslav Falico
This patchset introduces all the needed infrastructure, on top of current
adjacent lists, to be able to remove bond's slave_list/slave->list. The
overhead in memory/CPU is minimal, and after the patchset bonding can rely
on its slave-related functions, given the proper locking. I've done some
netperf benchmarks on a vm, and the delta was about 0.1gbps for 35gbps as a
whole, so no speed fluctuations.
It also automatically creates lower/upper and master symlinks in dev's
sysfs directory.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
CC: Dimitris Michailidis <dm@chelsio.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: Patrick McHardy <kaber@trash.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
v4 -> v5:
Remove casting from void * to slave *, it's not needed, in 06/27.
v3 -> v4:
Per the feedback received, fix the comments to be kernel-doc style.
As Ben Hutchings suggested, make the 'get next private after a
specific private' function bonding-specific - it has virtually no uses
outside bonding (and even in bonding I already have some patches of
removing it).
Also, remove the stupid 'bool upper' logic from everywhere in the logic -
as Ben suggested, it's easier to pass the lists directly - and not only
easier, it saved several hundred lines of code modified.
Finally, make netdev_for_each_lower_private() safe for removal of the
current member - it can be easily achieved and doesn't really need two
versions, as in lists.
v2 -> v3:
Fix the commit subject for patch 08 - forgot the _continue in
bond_for_each_slave_continue_reverse(), suggested by Cong Wang.
This version is already ready for the inclusion, hopefully.
Moved the changelog in cover letter to the bottom and cleaned it
up a bit.
v1 -> v2:
Fix a bug when we could remove try to remove a neighbour twice - it was
possible if we've had this neighbour already and added another devices
which had this neighbour in its lists. Fix it by following the rule - there
can be only one neighbour link, so add also _remove_neighbour() functions
to the generic _remove()s to handle the neighbour only removing, and fix
its refcounting while adding (all in patch 01).
Also, fix a vlan bug when it called unregister netdevice before unlinking -
it could possibly lead to a subte race condition - cause it was
unregistered but still in global-accessible list.
Rearrange sysfs/vlan patches so that first we fix vlan and only after we
add sysfs stuff.
RFC -> v1:
I've added proper, consistent naming for all variables/functions, uninlined
some helpers to get better backtraces, just in case (overhead is minimal,
no hot paths), rearranged patches for better review, dropped bondings
->prev and bond_for_each_slave_continue() functionality - to be able to
RCUify it easier, and renamed slave_* sysfs links to lower_* sysfs links to
maintain upper/lower naming. I've also dropped, thanks to bonding cleanup,
some heavy and ugly/intrusive patches.
---
drivers/net/bonding/bond_3ad.c | 54 ++--
drivers/net/bonding/bond_alb.c | 81 ++---
drivers/net/bonding/bond_alb.h | 4 +-
drivers/net/bonding/bond_main.c | 296 +++++++++--------
drivers/net/bonding/bond_procfs.c | 5 +-
drivers/net/bonding/bond_sysfs.c | 62 +---
drivers/net/bonding/bonding.h | 101 +++---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 +-
include/linux/netdevice.h | 55 +++-
net/8021q/vlan.c | 18 +-
net/core/dev.c | 403 +++++++++++++++++-------
11 files changed, 638 insertions(+), 444 deletions(-)
^ permalink raw reply
* [PATCH v5 net-next 02/27] net: add adj_list to save only neighbours
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev
Cc: jiri, Veaceslav Falico, David S. Miller, Eric Dumazet,
Alexander Duyck, Cong Wang
In-Reply-To: <1380093632-1842-1-git-send-email-vfalico@redhat.com>
Currently, we distinguish neighbours (first-level linked devices) from
non-neighbours by the neighbour bool in the netdev_adjacent. This could be
quite time-consuming in case we would like to traverse *only* through
neighbours - cause we'd have to traverse through all devices and check for
this flag, and in a (quite common) scenario where we have lots of vlans on
top of bridge, which is on top of a bond - the bonding would have to go
through all those vlans to get its upper neighbour linked devices.
This situation is really unpleasant, cause there are already a lot of cases
when a device with slaves needs to go through them in hot path.
To fix this, introduce a new upper/lower device lists structure -
adj_list, which contains only the neighbours. It works always in
pair with the all_adj_list structure (renamed from upper/lower_dev_list),
i.e. both of them contain the same links, only that all_adj_list contains
also non-neighbour device links. It's really a small change visible,
currently, only for __netdev_adjacent_dev_insert/remove(), and doesn't
change the main linked logic at all.
Also, add some comments a fix a name collision in
netdev_for_each_upper_dev_rcu() and rework the naming by the following
rules:
netdev_(all_)(upper|lower)_*
If "all_" is present, then we work with the whole list of upper/lower
devices, otherwise - only with direct neighbours. Uninline functions - to
get better stack traces.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v4 -> v5
No change.
v3 -> v4
Remove the 'bool upper' and, instead, transmit pointers to the lists
directly.
v2 -> v3:
No change.
v1 -> v2:
Fix a bug when we've tried to add a non-neighbour dev1 to dev2, while dev2
already had dev1 as a neighbour - we shouldn't care about neighbour's
ref_nr at all cause we can only add one - so just add/remove it via
different functions. And it became more readable.
RFC -> v1:
rename neighbour_dev_list/all_dev_list to adj_list/all_adj_list and rework
the naming of functions - to make the use the pattern
netdev_(all_)(lower|upper)_* . Uninline functions to get better stack
traces - inline doesn't give much speed improvement, but this way the stack
traces are meaningful.
drivers/net/bonding/bond_alb.c | 2 +-
drivers/net/bonding/bond_main.c | 10 +-
include/linux/netdevice.h | 28 ++++--
net/core/dev.c | 203 ++++++++++++++++++++--------------------
4 files changed, 129 insertions(+), 114 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f428ef57..8524e33 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1019,7 +1019,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
/* loop through vlans and send one packet for each */
rcu_read_lock();
- netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
if (upper->priv_flags & IFF_802_1Q_VLAN)
alb_send_lp_vid(slave, mac_addr,
vlan_dev_vlan_id(upper));
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 55bbb8b..91c4ab8 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2267,7 +2267,7 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
return true;
rcu_read_lock();
- netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
if (ip == bond_confirm_addr(upper, 0, ip)) {
ret = true;
break;
@@ -2342,10 +2342,12 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
*
* TODO: QinQ?
*/
- netdev_for_each_upper_dev_rcu(bond->dev, vlan_upper, vlan_iter) {
+ netdev_for_each_all_upper_dev_rcu(bond->dev, vlan_upper,
+ vlan_iter) {
if (!is_vlan_dev(vlan_upper))
continue;
- netdev_for_each_upper_dev_rcu(vlan_upper, upper, iter) {
+ netdev_for_each_all_upper_dev_rcu(vlan_upper, upper,
+ iter) {
if (upper == rt->dst.dev) {
vlan_id = vlan_dev_vlan_id(vlan_upper);
rcu_read_unlock();
@@ -2358,7 +2360,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
* our upper vlans, then just search for any dev that
* matches, and in case it's a vlan - save the id
*/
- netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
if (upper == rt->dst.dev) {
/* if it's a vlan - get its VID */
if (is_vlan_dev(upper))
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3de49ac..514045c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1143,8 +1143,18 @@ struct net_device {
struct list_head dev_list;
struct list_head napi_list;
struct list_head unreg_list;
- struct list_head upper_dev_list; /* List of upper devices */
- struct list_head lower_dev_list;
+
+ /* directly linked devices, like slaves for bonding */
+ struct {
+ struct list_head upper;
+ struct list_head lower;
+ } adj_list;
+
+ /* all linked devices, *including* neighbours */
+ struct {
+ struct list_head upper;
+ struct list_head lower;
+ } all_adj_list;
/* currently active device features */
@@ -2813,15 +2823,15 @@ extern int bpf_jit_enable;
extern bool netdev_has_upper_dev(struct net_device *dev,
struct net_device *upper_dev);
extern bool netdev_has_any_upper_dev(struct net_device *dev);
-extern struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
- struct list_head **iter);
+extern 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, upper, iter) \
- for (iter = &(dev)->upper_dev_list, \
- upper = netdev_upper_get_next_dev_rcu(dev, &(iter)); \
- upper; \
- upper = netdev_upper_get_next_dev_rcu(dev, &(iter)))
+#define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \
+ for (iter = &(dev)->all_adj_list.upper, \
+ updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)); \
+ updev; \
+ updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)))
extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 9be7937..9a395e0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4373,9 +4373,6 @@ struct netdev_adjacent {
/* upper master flag, there can only be one master device per list */
bool master;
- /* indicates that this dev is our first-level lower/upper device */
- bool neighbour;
-
/* counter for the number of times this device was added to us */
u16 ref_nr;
@@ -4385,29 +4382,17 @@ struct netdev_adjacent {
static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
struct net_device *adj_dev,
- struct list_head *dev_list)
+ struct list_head *adj_list)
{
struct netdev_adjacent *adj;
- list_for_each_entry(adj, dev_list, list) {
+ list_for_each_entry(adj, adj_list, list) {
if (adj->dev == adj_dev)
return adj;
}
return NULL;
}
-static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
- struct net_device *udev)
-{
- return __netdev_find_adj(dev, udev, &dev->upper_dev_list);
-}
-
-static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev,
- struct net_device *ldev)
-{
- return __netdev_find_adj(dev, ldev, &dev->lower_dev_list);
-}
-
/**
* netdev_has_upper_dev - Check if device is linked to an upper device
* @dev: device
@@ -4422,7 +4407,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
{
ASSERT_RTNL();
- return __netdev_find_upper(dev, upper_dev);
+ return __netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper);
}
EXPORT_SYMBOL(netdev_has_upper_dev);
@@ -4437,7 +4422,7 @@ bool netdev_has_any_upper_dev(struct net_device *dev)
{
ASSERT_RTNL();
- return !list_empty(&dev->upper_dev_list);
+ return !list_empty(&dev->all_adj_list.upper);
}
EXPORT_SYMBOL(netdev_has_any_upper_dev);
@@ -4454,10 +4439,10 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
ASSERT_RTNL();
- if (list_empty(&dev->upper_dev_list))
+ if (list_empty(&dev->adj_list.upper))
return NULL;
- upper = list_first_entry(&dev->upper_dev_list,
+ upper = list_first_entry(&dev->adj_list.upper,
struct netdev_adjacent, list);
if (likely(upper->master))
return upper->dev;
@@ -4465,15 +4450,15 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
-/* netdev_upper_get_next_dev_rcu - Get the next dev from upper list
+/* netdev_all_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 net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
+ struct list_head **iter)
{
struct netdev_adjacent *upper;
@@ -4481,14 +4466,14 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
- if (&upper->list == &dev->upper_dev_list)
+ if (&upper->list == &dev->all_adj_list.upper)
return NULL;
*iter = &upper->list;
return upper->dev;
}
-EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu);
/**
* netdev_master_upper_dev_get_rcu - Get master upper device
@@ -4501,7 +4486,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
{
struct netdev_adjacent *upper;
- upper = list_first_or_null_rcu(&dev->upper_dev_list,
+ upper = list_first_or_null_rcu(&dev->adj_list.upper,
struct netdev_adjacent, list);
if (upper && likely(upper->master))
return upper->dev;
@@ -4512,14 +4497,13 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
static int __netdev_adjacent_dev_insert(struct net_device *dev,
struct net_device *adj_dev,
struct list_head *dev_list,
- bool neighbour, bool master)
+ bool master)
{
struct netdev_adjacent *adj;
adj = __netdev_find_adj(dev, adj_dev, dev_list);
if (adj) {
- BUG_ON(neighbour);
adj->ref_nr++;
return 0;
}
@@ -4530,13 +4514,11 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->dev = adj_dev;
adj->master = master;
- adj->neighbour = neighbour;
adj->ref_nr = 1;
-
dev_hold(adj_dev);
- pr_debug("dev_hold for %s, because of %s link added from %s to %s\n",
- adj_dev->name, dev_list == &dev->upper_dev_list ?
- "upper" : "lower", dev->name, adj_dev->name);
+
+ pr_debug("dev_hold for %s, because of link added from %s to %s\n",
+ adj_dev->name, dev->name, adj_dev->name);
/* Ensure that master link is always the first item in list. */
if (master)
@@ -4547,22 +4529,6 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
return 0;
}
-static inline int __netdev_upper_dev_insert(struct net_device *dev,
- struct net_device *udev,
- bool master, bool neighbour)
-{
- return __netdev_adjacent_dev_insert(dev, udev, &dev->upper_dev_list,
- neighbour, master);
-}
-
-static inline int __netdev_lower_dev_insert(struct net_device *dev,
- struct net_device *ldev,
- bool neighbour)
-{
- return __netdev_adjacent_dev_insert(dev, ldev, &dev->lower_dev_list,
- neighbour, false);
-}
-
void __netdev_adjacent_dev_remove(struct net_device *dev,
struct net_device *adj_dev,
struct list_head *dev_list)
@@ -4571,73 +4537,102 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
adj = __netdev_find_adj(dev, adj_dev, dev_list);
- if (!adj)
+ if (!adj) {
+ pr_err("tried to remove device %s from %s\n",
+ dev->name, adj_dev->name);
BUG();
+ }
if (adj->ref_nr > 1) {
+ pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name,
+ adj->ref_nr-1);
adj->ref_nr--;
return;
}
list_del_rcu(&adj->list);
- pr_debug("dev_put for %s, because of %s link removed from %s to %s\n",
- adj_dev->name, dev_list == &dev->upper_dev_list ?
- "upper" : "lower", dev->name, adj_dev->name);
+ pr_debug("dev_put for %s, because link removed from %s to %s\n",
+ adj_dev->name, dev->name, adj_dev->name);
dev_put(adj_dev);
kfree_rcu(adj, rcu);
}
-static inline void __netdev_upper_dev_remove(struct net_device *dev,
- struct net_device *udev)
-{
- return __netdev_adjacent_dev_remove(dev, udev, &dev->upper_dev_list);
-}
-
-static inline void __netdev_lower_dev_remove(struct net_device *dev,
- struct net_device *ldev)
-{
- return __netdev_adjacent_dev_remove(dev, ldev, &dev->lower_dev_list);
-}
-
-int __netdev_adjacent_dev_insert_link(struct net_device *dev,
- struct net_device *upper_dev,
- bool master, bool neighbour)
+int __netdev_adjacent_dev_link_lists(struct net_device *dev,
+ struct net_device *upper_dev,
+ struct list_head *up_list,
+ struct list_head *down_list,
+ bool master)
{
int ret;
- ret = __netdev_upper_dev_insert(dev, upper_dev, master, neighbour);
+ ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, master);
if (ret)
return ret;
- ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour);
+ ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, false);
if (ret) {
- __netdev_upper_dev_remove(dev, upper_dev);
+ __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
return ret;
}
return 0;
}
-static inline int __netdev_adjacent_dev_link(struct net_device *dev,
- struct net_device *udev)
+int __netdev_adjacent_dev_link(struct net_device *dev,
+ struct net_device *upper_dev)
{
- return __netdev_adjacent_dev_insert_link(dev, udev, false, false);
+ return __netdev_adjacent_dev_link_lists(dev, upper_dev,
+ &dev->all_adj_list.upper,
+ &upper_dev->all_adj_list.lower,
+ false);
}
-static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
- struct net_device *udev,
- bool master)
+void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
+ struct net_device *upper_dev,
+ struct list_head *up_list,
+ struct list_head *down_list)
{
- return __netdev_adjacent_dev_insert_link(dev, udev, master, true);
+ __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
+ __netdev_adjacent_dev_remove(upper_dev, dev, down_list);
}
void __netdev_adjacent_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
- __netdev_upper_dev_remove(dev, upper_dev);
- __netdev_lower_dev_remove(upper_dev, dev);
+ __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
+ &dev->all_adj_list.upper,
+ &upper_dev->all_adj_list.lower);
+}
+
+int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
+ struct net_device *upper_dev,
+ bool master)
+{
+ int ret = __netdev_adjacent_dev_link(dev, upper_dev);
+
+ if (ret)
+ return ret;
+
+ ret = __netdev_adjacent_dev_link_lists(dev, upper_dev,
+ &dev->adj_list.upper,
+ &upper_dev->adj_list.lower,
+ master);
+ if (ret) {
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
+ return ret;
+ }
+
+ return 0;
}
+void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
+ __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
+ &dev->adj_list.upper,
+ &upper_dev->adj_list.lower);
+}
static int __netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev, bool master)
@@ -4651,10 +4646,10 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return -EBUSY;
/* To prevent loops, check if dev is not upper device to upper_dev. */
- if (__netdev_find_upper(upper_dev, dev))
+ if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper))
return -EBUSY;
- if (__netdev_find_upper(dev, upper_dev))
+ if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper))
return -EEXIST;
if (master && netdev_master_upper_dev_get(dev))
@@ -4665,12 +4660,14 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return ret;
/* Now that we linked these devs, make all the upper_dev's
- * upper_dev_list visible to every dev's lower_dev_list and vice
+ * all_adj_list.upper visible to every dev's all_adj_list.lower an
* versa, and don't forget the devices itself. All of these
* links are non-neighbours.
*/
- list_for_each_entry(i, &dev->lower_dev_list, list) {
- list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
+ pr_debug("Interlinking %s with %s, non-neighbour\n",
+ i->dev->name, j->dev->name);
ret = __netdev_adjacent_dev_link(i->dev, j->dev);
if (ret)
goto rollback_mesh;
@@ -4678,14 +4675,18 @@ static int __netdev_upper_dev_link(struct net_device *dev,
}
/* add dev to every upper_dev's upper device */
- list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
+ pr_debug("linking %s's upper device %s with %s\n",
+ upper_dev->name, i->dev->name, dev->name);
ret = __netdev_adjacent_dev_link(dev, i->dev);
if (ret)
goto rollback_upper_mesh;
}
/* add upper_dev to every dev's lower device */
- list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
+ pr_debug("linking %s's lower device %s with %s\n", dev->name,
+ i->dev->name, upper_dev->name);
ret = __netdev_adjacent_dev_link(i->dev, upper_dev);
if (ret)
goto rollback_lower_mesh;
@@ -4696,7 +4697,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
rollback_lower_mesh:
to_i = i;
- list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
@@ -4706,7 +4707,7 @@ rollback_lower_mesh:
rollback_upper_mesh:
to_i = i;
- list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(dev, i->dev);
@@ -4717,8 +4718,8 @@ rollback_upper_mesh:
rollback_mesh:
to_i = i;
to_j = j;
- list_for_each_entry(i, &dev->lower_dev_list, list) {
- list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
if (i == to_i && j == to_j)
break;
__netdev_adjacent_dev_unlink(i->dev, j->dev);
@@ -4727,7 +4728,7 @@ rollback_mesh:
break;
}
- __netdev_adjacent_dev_unlink(dev, upper_dev);
+ __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
return ret;
}
@@ -4781,23 +4782,23 @@ void netdev_upper_dev_unlink(struct net_device *dev,
struct netdev_adjacent *i, *j;
ASSERT_RTNL();
- __netdev_adjacent_dev_unlink(dev, upper_dev);
+ __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
/* Here is the tricky part. We must remove all dev's lower
* devices from all upper_dev's upper devices and vice
* versa, to maintain the graph relationship.
*/
- list_for_each_entry(i, &dev->lower_dev_list, list)
- list_for_each_entry(j, &upper_dev->upper_dev_list, list)
+ list_for_each_entry(i, &dev->all_adj_list.lower, list)
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list)
__netdev_adjacent_dev_unlink(i->dev, j->dev);
/* remove also the devices itself from lower/upper device
* list
*/
- list_for_each_entry(i, &dev->lower_dev_list, list)
+ list_for_each_entry(i, &dev->all_adj_list.lower, list)
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
- list_for_each_entry(i, &upper_dev->upper_dev_list, list)
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
__netdev_adjacent_dev_unlink(dev, i->dev);
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
@@ -6059,8 +6060,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->link_watch_list);
- INIT_LIST_HEAD(&dev->upper_dev_list);
- INIT_LIST_HEAD(&dev->lower_dev_list);
+ INIT_LIST_HEAD(&dev->adj_list.upper);
+ INIT_LIST_HEAD(&dev->adj_list.lower);
+ INIT_LIST_HEAD(&dev->all_adj_list.upper);
+ INIT_LIST_HEAD(&dev->all_adj_list.lower);
dev->priv_flags = IFF_XMIT_DST_RELEASE;
setup(dev);
--
1.8.4
^ permalink raw reply related
* [PATCH v5 net-next 01/27] net: use lists as arguments instead of bool upper
From: Veaceslav Falico @ 2013-09-25 7:20 UTC (permalink / raw)
To: netdev
Cc: jiri, Veaceslav Falico, David S. Miller, Eric Dumazet,
Alexander Duyck, Cong Wang
In-Reply-To: <1380093632-1842-1-git-send-email-vfalico@redhat.com>
Currently we make use of bool upper when we want to specify if we want to
work with upper/lower list. It's, however, harder to read, debug and
occupies a lot more code.
Fix this by just passing the correct upper/lower_dev_list list_head pointer
instead of bool upper, and work internally with it.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v4 -> v5
No change.
RFC -> v4:
New patch.
net/core/dev.c | 54 ++++++++++++++++++++++--------------------------------
1 file changed, 22 insertions(+), 32 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 5c713f2..9be7937 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4385,12 +4385,9 @@ struct netdev_adjacent {
static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
struct net_device *adj_dev,
- bool upper)
+ struct list_head *dev_list)
{
struct netdev_adjacent *adj;
- struct list_head *dev_list;
-
- dev_list = upper ? &dev->upper_dev_list : &dev->lower_dev_list;
list_for_each_entry(adj, dev_list, list) {
if (adj->dev == adj_dev)
@@ -4402,13 +4399,13 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
struct net_device *udev)
{
- return __netdev_find_adj(dev, udev, true);
+ return __netdev_find_adj(dev, udev, &dev->upper_dev_list);
}
static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev,
struct net_device *ldev)
{
- return __netdev_find_adj(dev, ldev, false);
+ return __netdev_find_adj(dev, ldev, &dev->lower_dev_list);
}
/**
@@ -4514,12 +4511,12 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
static int __netdev_adjacent_dev_insert(struct net_device *dev,
struct net_device *adj_dev,
- bool neighbour, bool master,
- bool upper)
+ struct list_head *dev_list,
+ bool neighbour, bool master)
{
struct netdev_adjacent *adj;
- adj = __netdev_find_adj(dev, adj_dev, upper);
+ adj = __netdev_find_adj(dev, adj_dev, dev_list);
if (adj) {
BUG_ON(neighbour);
@@ -4538,19 +4535,14 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
dev_hold(adj_dev);
pr_debug("dev_hold for %s, because of %s link added from %s to %s\n",
- adj_dev->name, upper ? "upper" : "lower", dev->name,
- adj_dev->name);
+ adj_dev->name, dev_list == &dev->upper_dev_list ?
+ "upper" : "lower", dev->name, adj_dev->name);
- if (!upper) {
- list_add_tail_rcu(&adj->list, &dev->lower_dev_list);
- return 0;
- }
-
- /* Ensure that master upper link is always the first item in list. */
+ /* Ensure that master link is always the first item in list. */
if (master)
- list_add_rcu(&adj->list, &dev->upper_dev_list);
+ list_add_rcu(&adj->list, dev_list);
else
- list_add_tail_rcu(&adj->list, &dev->upper_dev_list);
+ list_add_tail_rcu(&adj->list, dev_list);
return 0;
}
@@ -4559,27 +4551,25 @@ static inline int __netdev_upper_dev_insert(struct net_device *dev,
struct net_device *udev,
bool master, bool neighbour)
{
- return __netdev_adjacent_dev_insert(dev, udev, neighbour, master,
- true);
+ return __netdev_adjacent_dev_insert(dev, udev, &dev->upper_dev_list,
+ neighbour, master);
}
static inline int __netdev_lower_dev_insert(struct net_device *dev,
struct net_device *ldev,
bool neighbour)
{
- return __netdev_adjacent_dev_insert(dev, ldev, neighbour, false,
- false);
+ return __netdev_adjacent_dev_insert(dev, ldev, &dev->lower_dev_list,
+ neighbour, false);
}
void __netdev_adjacent_dev_remove(struct net_device *dev,
- struct net_device *adj_dev, bool upper)
+ struct net_device *adj_dev,
+ struct list_head *dev_list)
{
struct netdev_adjacent *adj;
- if (upper)
- adj = __netdev_find_upper(dev, adj_dev);
- else
- adj = __netdev_find_lower(dev, adj_dev);
+ adj = __netdev_find_adj(dev, adj_dev, dev_list);
if (!adj)
BUG();
@@ -4591,8 +4581,8 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
list_del_rcu(&adj->list);
pr_debug("dev_put for %s, because of %s link removed from %s to %s\n",
- adj_dev->name, upper ? "upper" : "lower", dev->name,
- adj_dev->name);
+ adj_dev->name, dev_list == &dev->upper_dev_list ?
+ "upper" : "lower", dev->name, adj_dev->name);
dev_put(adj_dev);
kfree_rcu(adj, rcu);
}
@@ -4600,13 +4590,13 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
static inline void __netdev_upper_dev_remove(struct net_device *dev,
struct net_device *udev)
{
- return __netdev_adjacent_dev_remove(dev, udev, true);
+ return __netdev_adjacent_dev_remove(dev, udev, &dev->upper_dev_list);
}
static inline void __netdev_lower_dev_remove(struct net_device *dev,
struct net_device *ldev)
{
- return __netdev_adjacent_dev_remove(dev, ldev, false);
+ return __netdev_adjacent_dev_remove(dev, ldev, &dev->lower_dev_list);
}
int __netdev_adjacent_dev_insert_link(struct net_device *dev,
--
1.8.4
^ permalink raw reply related
* Re: [RFC PATCHv2 0/4] Add DT support for fixed PHYs
From: Christian Gmeiner @ 2013-09-25 7:12 UTC (permalink / raw)
To: Thomas Petazzoni, David S. Miller, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Florian Fainelli, Lior Amsalem,
Gregory Clement, Ezequiel Garcia,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Mark Rutland,
Christian Gmeiner
In-Reply-To: <20130911064248.GI30088-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Hi
>> Hello,
>>
>> Here is a second version of the patch set that adds a Device Tree
>> binding and the related code to support fixed PHYs. Marked as RFC,
>> this patch set is obviously not intended for merging in 3.12.
>>
>> Since the first version, the changes have been:
>>
>> * Instead of using a 'fixed-link' property inside the Ethernet device
>> DT node, with a fairly cryptic succession of integer values, we now
>> use a PHY subnode under the Ethernet device DT node, with explicit
>> properties to configure the duplex, speed, pause and other PHY
>> properties.
>>
>> * The PHY address is automatically allocated by the kernel and no
>> longer visible in the Device Tree binding.
>>
>> * The PHY device is created directly when the network driver calls
>> of_phy_connect_fixed_link(), and associated to the PHY DT node,
>> which allows the existing of_phy_connect() function to work,
>> without the need to use the deprecated of_phy_connect_fixed_link().
>>
>> The things I am not entirely happy with yet are:
>>
>> * The PHY ID is hardcoded to 0xdeadbeef. Ideally, it should be a
>> properly reserved vendor/device identifier, but it isn't clear how
>> to get one allocated for this purpose.
>>
>> * The fixed_phy_register() function in drivers/net/phy/fixed.c has
>> some OF references. So ideally, I would have preferred to put this
>> code in drivers/of/of_mdio.c, but to call get_phy_device(), we need
>> a reference to the mii_bus structure that represents the fixed MDIO
>> bus.
>>
>> * There is some error management missing in fixed_phy_register(), but
>> it can certainly be added easily. This RFC is meant to sort out the
>> general idea.
>
> +1 for the general idea. This really looks good now. I've not much more
> to say. Maybe someone from the devicetree corner has a few words for the
> binding?
>
I tested the whole series with an I.MX6D board with the FEC driver:
fec 2188000.ethernet eth0: Freescale FEC PHY driver [Generic PHY]
(mii_bus:phy_addr=fixed-0:00, irq=-1)
For me binding looks nice and I hope to see this patch series in 3.13.
Tested-by: Christian Gmeiner <christian.gmeiner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
--
Christian Gmeiner, MSc
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] Allow userspace code to use flag IFA_F_SECONDARY to specify an ip address to be primary or secondary ip on an interface
From: Julian Anastasov @ 2013-09-25 7:08 UTC (permalink / raw)
To: Vincent Li; +Cc: netdev@vger.kernel.org, linux-kernel, davem
In-Reply-To: <CAK3+h2y8eAKFC7BbnDwfZLzTw=t-G9qWSqznp4ggwDy7R_O6Ag@mail.gmail.com>
Hello,
On Tue, 24 Sep 2013, Vincent Li wrote:
> Thanks Julian for the comments, I imagined it would not be so simple
> as it changed old behavior with ip binary and some actions in
> __inet_del_ifa() that I am not fully aware of. my intention is to
> preserve the old behavior and extend the flexibility, I am unable to
> come up with a good patch to achieve the intended behavior.
...
> if someone can point me to the right patch directions or coming up
> with better patches, it is very much appreciated.
My first idea was to use NLM_F_APPEND to implement
'ip addr prepend' and 'ip addr append' but the default
operation is 'append' without providing NLM_F_APPEND, so it
does not work.
Another idea is to add new attribute IFA_PREFERENCE in
include/uapi/linux/if_addr.h just before __IFA_MAX, integer,
3 of the values are known. A preference for the used scope.
/* Add as last, default */
IFA_PREFERENCE_APPEND = 0,
/* Add as last primary, before any present primary in subnet */
IFA_PREFERENCE_PRIMARY = 128,
/* First for scope */
IFA_PREFERENCE_FIRST = 255,
We should keep it in ifa as priority, for
sorting purposes. It can be 4-byte value, if user wants
to copy user-defined order into preference.
Sorting order should be:
- all primaries sorted by decreasing scope, decreasing
priority and adding order
- then all secondaries (IFA_F_SECONDARY) sorted by decreasing
priority and adding order
Usage:
ip addr add ... pref[erence] type_or_priority
# Add floating IP (append at priority 128)
# The primary mode is not guaranteed if another address from
# the same subnet is already using the same or higher priority.
ip addr add ... pref primary
# More preferred primary
ip addr add ... pref 129
# Add first IP for scope
ip addr add ... pref first
The scope has similar 'sorting' property but not
for IPs in same subnet and it would be difficult to use
it for global routes.
Thoughts?
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* Let the moment last as much as you want.
From: BarrettDavis @ 2013-09-25 6:44 UTC (permalink / raw)
Dear Customer,
Sometimes things happen much quicker than you would love to.
Let the moment last as much as you want.
http://translate.googleusercontent.com/translate_c?depth=1&hl=auto&sl=de&url=www.google.dk&u=http://onlineshop57.yolasite.com/store&usg=ALkJrhjsEp2wEy6D4p3zB8y4lFpDcS7xmg
Best Regards,
^ permalink raw reply
* [PATCH net 2/2] ip_tunnel: Add fallback tunnels to the hash lists
From: Steffen Klassert @ 2013-09-25 5:55 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20130925055418.GV7660@secunet.com>
Currently we can not update the tunnel parameters of
the fallback tunnels because we don't find them in the
hash lists. Fix this by adding them on initialization.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_tunnel.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index b8ce640..f2348f2 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -853,8 +853,10 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
/* FB netdevice is special: we have one, and only one per netns.
* Allowing to move it to another netns is clearly unsafe.
*/
- if (!IS_ERR(itn->fb_tunnel_dev))
+ if (!IS_ERR(itn->fb_tunnel_dev)) {
itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
+ ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
+ }
rtnl_unlock();
return PTR_RET(itn->fb_tunnel_dev);
--
1.7.9.5
^ permalink raw reply related
* [PATCH net 1/2] ip_tunnel: Fix a memory corruption in ip_tunnel_xmit
From: Steffen Klassert @ 2013-09-25 5:54 UTC (permalink / raw)
To: David Miller; +Cc: netdev
We might extend the used aera of a skb beyond the total
headroom when we install the ipip header. Fix this by
calling skb_cow_head() unconditionally.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_tunnel.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index ac9fabe..b8ce640 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -641,13 +641,13 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
+ rt->dst.header_len;
- if (max_headroom > dev->needed_headroom) {
+ if (max_headroom > dev->needed_headroom)
dev->needed_headroom = max_headroom;
- if (skb_cow_head(skb, dev->needed_headroom)) {
- dev->stats.tx_dropped++;
- dev_kfree_skb(skb);
- return;
- }
+
+ if (skb_cow_head(skb, dev->needed_headroom)) {
+ dev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ return;
}
err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol,
--
1.7.9.5
^ permalink raw reply related
* Re: linux-next: manual merge of the ipsec-next tree with the net-next tree
From: Steffen Klassert @ 2013-09-25 5:29 UTC (permalink / raw)
To: Stephen Rothwell
Cc: linux-next, linux-kernel, Fan Du, Joe Perches, David Miller,
netdev
In-Reply-To: <20130925095919.143635403832766c1b190202@canb.auug.org.au>
On Wed, Sep 25, 2013 at 09:59:19AM +1000, Stephen Rothwell wrote:
> Hi Steffen,
>
> On Tue, 24 Sep 2013 12:25:05 +0200 Steffen Klassert <steffen.klassert@secunet.com> wrote:
> >
> > On Tue, Sep 24, 2013 at 12:16:29PM +1000, Stephen Rothwell wrote:
> > >
> > > Today's linux-next merge of the ipsec-next tree got a conflict in
> > > include/net/xfrm.h between commit d511337a1eda ("xfrm.h: Remove extern
> > > from function prototypes") from the net-next tree and commit aba826958830
> > > ("{ipv4,xfrm}: Introduce xfrm_tunnel_notifier for xfrm tunnel mode
> > > callback") from the ipsec-next tree.
> >
> > Thanks for the information, I'll do a rebase of the ipsec-next
> > tree tomorrow.
>
> Did you miss the end of the next paragraph: "no action is required"?
> Dave can fix this up (like I did) when he merges your tree into his.
>
I applied this patch shortly before the merge window opened, it is a left
over from the last develpoment cycle. I already rebased my tree onto
net-next in the past if that happened, even if there were no merge
conflicts. I did that just to see if everything still works. But I
could also do a test merge to see if everything still works and ask
to pull without a rebase then if this is the prefered way. Would make
my life easier :)
^ permalink raw reply
* SCTP will not bind to link-local IPv6 address (3.9.11+ kernel)
From: Ben Greear @ 2013-09-25 3:48 UTC (permalink / raw)
To: netdev
I don't have time to track this down now, but I opened a bug so
the issue isn't lost.
https://bugzilla.kernel.org/show_bug.cgi?id=62051
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH tip/core/rcu 07/13] ipv6/ip6_tunnel: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
peterz, rostedt, dhowells, edumazet, darren, fweisbec, sbw,
Paul E. McKenney, David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the use in
ip6_tnl_unlink() is legitimate: It is assigning a pointer to an element
from an RCU-protected list, and all elements of this list are already
visible to caller.
This commit therefore silences this false positive by laundering the
pointer using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: netdev@vger.kernel.org
---
net/ipv6/ip6_tunnel.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 61355f7..ecc0166e 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -245,7 +245,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
(iter = rtnl_dereference(*tp)) != NULL;
tp = &iter->next) {
if (t == iter) {
- rcu_assign_pointer(*tp, t->next);
+ rcu_assign_pointer(*tp, rcu_access_pointer(t->next));
break;
}
}
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 13/13] bonding/bond_alb.c: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
peterz, rostedt, dhowells, edumazet, darren, fweisbec, sbw,
Paul E. McKenney, David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the use in
bond_alb_handle_active_change() is legitimate: It is assigning a pointer
to an element from an RCU-protected list, and all elements of this list
are already visible to caller.
This commit therefore silences this false positive by laundering the
pointer using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: netdev@vger.kernel.org
---
drivers/net/bonding/bond_alb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 91f179d..cdd697c 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1667,7 +1667,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
}
swap_slave = bond->curr_active_slave;
- rcu_assign_pointer(bond->curr_active_slave, new_slave);
+ rcu_assign_pointer(bond->curr_active_slave,
+ rcu_access_pointer(new_slave));
if (!new_slave || list_empty(&bond->slave_list))
return;
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 12/13] bonding/bond_main: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: Stephen Hemminger, tglx, laijs, edumazet, peterz, fweisbec,
bridge, josh, rostedt, David S. Miller, dhowells, sbw, niv,
netdev, mathieu.desnoyers, dipankar, darren, akpm,
Paul E. McKenney, mingo
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the uses in
bond_change_active_slave(), bond_enslave(), and __bond_release_one()
are legitimate: They are assigning a pointer to an element from an
RCU-protected list (or a NULL pointer), and all elements of this list
are already visible to caller.
This commit therefore silences these false positives either by laundering
the pointers using rcu_access_pointer() as suggested by Josh Triplett,
or by using RCU_INIT_POINTER() for NULL pointer assignments.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: bridge@lists.linux-foundation.org
Cc: netdev@vger.kernel.org
---
drivers/net/bonding/bond_main.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 72df399..2f276b9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -890,7 +890,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
if (new_active)
bond_set_slave_active_flags(new_active);
} else {
- rcu_assign_pointer(bond->curr_active_slave, new_active);
+ rcu_assign_pointer(bond->curr_active_slave,
+ rcu_access_pointer(new_active));
}
if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
@@ -1601,7 +1602,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* so we can change it without calling change_active_interface()
*/
if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
- rcu_assign_pointer(bond->curr_active_slave, new_slave);
+ rcu_assign_pointer(bond->curr_active_slave,
+ rcu_access_pointer(new_slave));
break;
} /* switch(bond_mode) */
@@ -1801,7 +1803,7 @@ static int __bond_release_one(struct net_device *bond_dev,
}
if (all) {
- rcu_assign_pointer(bond->curr_active_slave, NULL);
+ RCU_INIT_POINTER(bond->curr_active_slave, NULL);
} else if (oldcurrent == slave) {
/*
* Note that we hold RTNL over this sequence, so there
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 11/13] bridge/br_mdb: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
peterz, rostedt, dhowells, edumazet, darren, fweisbec, sbw,
Paul E. McKenney, Stephen Hemminger, David S. Miller, bridge,
netdev
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the use in
__br_mdb_del() is legitimate: They is assigning a pointer to an element
from an RCU-protected list, and all elements of this list are already
visible to caller.
This commit therefore silences these false positives by laundering the
pointers using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: bridge@lists.linux-foundation.org
Cc: netdev@vger.kernel.org
---
net/bridge/br_mdb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 85a09bb..3184c88 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -447,7 +447,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
if (p->port->state == BR_STATE_DISABLED)
goto unlock;
- rcu_assign_pointer(*pp, p->next);
+ rcu_assign_pointer(*pp, rcu_access_pointer(p->next));
hlist_del_init(&p->mglist);
del_timer(&p->timer);
call_rcu_bh(&p->rcu, br_multicast_free_pg);
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 10/13] mac80211: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: mingo-DgEjT+Ai2ygdnm+yROfE0A, laijs-BthXqXjhjHXQFUHtdCDX3A,
dipankar-xthvdsQ13ZrQT0dZR+AlfA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w,
josh-iaAMLnmF4UmaiuxdJuQwMA, niv-r/Jw6+rmf7HQT0dZR+AlfA,
tglx-hfZtesqFncYOwBW4kG4KsQ, peterz-wEGCiKHe2LqWVfeAwA7xHQ,
rostedt-nx8X9YLhiw1AfugRpC6u6w, dhowells-H+wXaHxf7aLQT0dZR+AlfA,
edumazet-hpIqsD4AKlfQT0dZR+AlfA, darren-P76s1CtE8BHQT0dZR+AlfA,
fweisbec-Re5JQEeQqe8AvxtiuMwx3w, sbw-3s7WtUTddSA,
Paul E. McKenney, John W. Linville, Johannes Berg,
David S. Miller, linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
From: "Paul E. McKenney" <paulmck-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the uses in
sta_info_hash_del() are legitimate: They is assigning a pointer to an
element from an RCU-protected list, and all elements of this list are
already visible to caller.
This commit therefore silences this false positive by laundering the
pointer using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Paul E. McKenney <paulmck-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Cc: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Cc: Johannes Berg <johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
net/mac80211/sta_info.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aeb967a..d18ab89 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -75,7 +75,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
return -ENOENT;
if (s == sta) {
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)],
- s->hnext);
+ rcu_access_pointer(s->hnext));
return 0;
}
@@ -84,7 +84,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
s = rcu_dereference_protected(s->hnext,
lockdep_is_held(&local->sta_mtx));
if (rcu_access_pointer(s->hnext)) {
- rcu_assign_pointer(s->hnext, sta->hnext);
+ rcu_assign_pointer(s->hnext, rcu_access_pointer(sta->hnext));
return 0;
}
--
1.8.1.5
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH tip/core/rcu 09/13] ipv6/sit: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
peterz, rostedt, dhowells, edumazet, darren, fweisbec, sbw,
Paul E. McKenney, David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the use in
ipip6_tunnel_unlink() is legitimate: It is assigning a pointer to an
element from an RCU-protected list, and all elements of this list are
already visible to caller.
This commit therefore silences this false positive by laundering the
pointer using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: netdev@vger.kernel.org
---
net/ipv6/sit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 7ee5cb9..fcb050a 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -157,7 +157,7 @@ static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
(iter = rtnl_dereference(*tp)) != NULL;
tp = &iter->next) {
if (t == iter) {
- rcu_assign_pointer(*tp, t->next);
+ rcu_assign_pointer(*tp, rcu_access_pointer(t->next));
break;
}
}
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 08/13] ipv6/ip6_gre: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
peterz, rostedt, dhowells, edumazet, darren, fweisbec, sbw,
Paul E. McKenney, David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the use in
ip6gre_tunnel_unlink() is legitimate: It is assigning a pointer to an
element from an RCU-protected list, and all elements of this list are
already visible to caller.
This commit therefore silences this false positive by laundering the
pointer using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: netdev@vger.kernel.org
---
net/ipv6/ip6_gre.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 6b26e9f..a0b8f40 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -276,7 +276,7 @@ static void ip6gre_tunnel_unlink(struct ip6gre_net *ign, struct ip6_tnl *t)
(iter = rtnl_dereference(*tp)) != NULL;
tp = &iter->next) {
if (t == iter) {
- rcu_assign_pointer(*tp, t->next);
+ rcu_assign_pointer(*tp, rcu_access_pointer(t->next));
break;
}
}
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 06/13] ipv4/ip_socketglue: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
peterz, rostedt, dhowells, edumazet, darren, fweisbec, sbw,
Paul E. McKenney, David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the use in
ip_ra_control() is legitimate: It is assigning a pointer to an element
from an RCU-protected list, and all elements of this list are already
visible to caller.
This commit therefore silences this false positive by laundering the
pointer using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: netdev@vger.kernel.org
---
net/ipv4/ip_sockglue.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index d9c4f11..d328f15 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -269,7 +269,7 @@ int ip_ra_control(struct sock *sk, unsigned char on,
}
/* dont let ip_call_ra_chain() use sk again */
ra->sk = NULL;
- rcu_assign_pointer(*rap, ra->next);
+ rcu_assign_pointer(*rap, rcu_access_pointer(ra->next));
spin_unlock_bh(&ip_ra_lock);
if (ra->destructor)
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 05/13] decnet: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
peterz, rostedt, dhowells, edumazet, darren, fweisbec, sbw,
Paul E. McKenney, David S. Miller, Thomas Graf, Gao feng,
Stephen Hemminger, linux-decnet-user, netdev
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the use in
dn_insert_route() is legitimate: It is assigning a pointer to an element
from an RCU-protected list, and all elements of this list are already
visible to caller.
This commit therefore silences this false positive by laundering the
pointer using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Graf <tgraf@suug.ch>
Cc: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: linux-decnet-user@lists.sourceforge.net
Cc: netdev@vger.kernel.org
---
net/decnet/dn_route.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index fe32388..3b1357b 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -345,7 +345,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou
/* Put it first */
*rthp = rth->dst.dn_next;
rcu_assign_pointer(rth->dst.dn_next,
- dn_rt_hash_table[hash].chain);
+ rcu_access_pointer(dn_rt_hash_table[hash].chain));
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
dst_use(&rth->dst, now);
@@ -358,7 +358,8 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou
rthp = &rth->dst.dn_next;
}
- rcu_assign_pointer(rt->dst.dn_next, dn_rt_hash_table[hash].chain);
+ rcu_assign_pointer(rt->dst.dn_next,
+ rcu_access_pointer(dn_rt_hash_table[hash].chain));
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
dst_use(&rt->dst, now);
--
1.8.1.5
^ permalink raw reply related
* [PATCH tip/core/rcu 04/13] wireless: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-09-25 1:35 UTC (permalink / raw)
To: linux-kernel
Cc: Stephen Hemminger, tglx, laijs, edumazet, peterz, fweisbec,
bridge, josh, rostedt, David S. Miller, dhowells, sbw, niv,
netdev, mathieu.desnoyers, dipankar, darren, akpm,
Paul E. McKenney, mingo
In-Reply-To: <1380072916-31557-1-git-send-email-paulmck@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The sparse checking for rcu_assign_pointer() was recently upgraded
to reject non-__kernel address spaces. This also rejects __rcu,
which is almost always the right thing to do. However, the uses in
cfg80211_combine_bsses() and cfg80211_bss_update() are legitimate:
They is assigning a pointer to an element from an RCU-protected list,
and all elements of this list are already visible to caller.
This commit therefore silences these false positives by laundering the
pointers using rcu_access_pointer() as suggested by Josh Triplett.
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: bridge@lists.linux-foundation.org
Cc: netdev@vger.kernel.org
---
net/wireless/scan.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index eeb7148..edde117 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -671,7 +671,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
bss->pub.hidden_beacon_bss = &new->pub;
new->refcount += bss->refcount;
rcu_assign_pointer(bss->pub.beacon_ies,
- new->pub.beacon_ies);
+ rcu_access_pointer(new->pub.beacon_ies));
}
return true;
@@ -706,10 +706,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
old = rcu_access_pointer(found->pub.proberesp_ies);
rcu_assign_pointer(found->pub.proberesp_ies,
- tmp->pub.proberesp_ies);
+ rcu_access_pointer(tmp->pub.proberesp_ies));
/* Override possible earlier Beacon frame IEs */
rcu_assign_pointer(found->pub.ies,
- tmp->pub.proberesp_ies);
+ rcu_access_pointer(tmp->pub.proberesp_ies));
if (old)
kfree_rcu((struct cfg80211_bss_ies *)old,
rcu_head);
@@ -740,12 +740,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
old = rcu_access_pointer(found->pub.beacon_ies);
rcu_assign_pointer(found->pub.beacon_ies,
- tmp->pub.beacon_ies);
+ rcu_access_pointer(tmp->pub.beacon_ies));
/* Override IEs if they were from a beacon before */
if (old == rcu_access_pointer(found->pub.ies))
rcu_assign_pointer(found->pub.ies,
- tmp->pub.beacon_ies);
+ rcu_access_pointer(tmp->pub.beacon_ies));
/* Assign beacon IEs to all sub entries */
list_for_each_entry(bss, &found->hidden_list,
@@ -756,7 +756,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
WARN_ON(ies != old);
rcu_assign_pointer(bss->pub.beacon_ies,
- tmp->pub.beacon_ies);
+ rcu_access_pointer(tmp->pub.beacon_ies));
}
if (old)
@@ -804,7 +804,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
&hidden->hidden_list);
hidden->refcount++;
rcu_assign_pointer(new->pub.beacon_ies,
- hidden->pub.beacon_ies);
+ rcu_access_pointer(hidden->pub.beacon_ies));
}
} else {
/*
--
1.8.1.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox