bonding: create bond_first_slave_rcu()
Subsystems (3)
PATCH v3 5/10 bonding: create bond_first_slave_rcu()
The bond_first_slave_rcu() will be used to instead of bond_first_slave() in rcu_read_lock().
So move the struct netdev_adjacent to the netdevice.h and make the bond_first_slave_rcu() could use the struct.
--- drivers/net/bonding/bonding.h | 9 +++++++++ include/linux/netdevice.h | 16 ++++++++++++++++ net/core/dev.c | 16 ---------------- 3 files changed, 25 insertions(+), 16 deletions(-)
drivers/net/bonding/bonding.h +9 -0
@@ -91,6 +91,15 @@ netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \ NULL) +/* Caller must have rcu_read_lock */ +#define bond_first_slave_rcu (bond) \ + ({struct list_head *__ptr = (bond_slave_list(bond)); \ + struct list_head *__next = ACCESS_ONCE(__ptr->next); \ + likely(__ptr != __next) ? \ + list_entry_rcu(__next, struct netdev_adjacent, list)->private : \ + NULL; \ + }) +#define bond_is_first_slave (bond, pos) (pos == bond_first_slave(bond))#define bond_is_last_slave (bond, pos) (pos == bond_last_slave(bond))
include/linux/netdevice.h +16 -0
@@ -2839,6 +2839,22 @@ extern int netdev_tstamp_prequeue;extern int weight_p;extern int bpf_jit_enable; +struct netdev_adjacent { +struct net_device *dev; + +/* upper master flag, there can only be one master device per list */ +bool master; + +/* 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; +}; +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_all_upper_get_next_dev_rcu(struct net_device *dev,
net/core/dev.c +0 -16
@@ -4377,22 +4377,6 @@ softnet_break: goto out; } -struct netdev_adjacent { -struct net_device *dev; - -/* upper master flag, there can only be one master device per list */ -bool master; - -/* 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; -}; -static struct netdev_adjacent *__netdev_find_adj_rcu (struct net_device *dev,struct net_device *adj_dev,struct list_head *adj_list)
Signature · 1 line
1.8.2.1
Quoted 5 lines · Ding Tianhong
The
bond_first_slave_rcu()will be used to instead ofbond_first_slave()inrcu_read_lock().So move the struct
netdev_adjacentto thenetdevice.hand make thebond_first_slave_rcu()could use the struct.
The whole point in netdev_adjacent functions was to hide it from the users who wanted to use it directly. See
http://www.spinics.net/lists/netdev/msg248026.html
for reference. Please try to avoid that.
Quoted 89 lines
Suggested-by Jay Vosburgh <[email protected]>Suggested-by Veaceslav Falico <[email protected]>Signed-off-by Ding Tianhong <[email protected]>---
drivers/net/bonding/bonding.h | 9 +++++++++ include/linux/netdevice.h | 16 ++++++++++++++++ net/core/dev.c | 16 ---------------- 3 files changed, 25 insertions(+), 16 deletions(-)drivers/net/bonding/bonding.h +9
-0@@ -91,6 +91,15 @@ netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \ NULL) +/* Caller must have rcu_read_lock */ +#define bond_first_slave_rcu (bond) \ + ({struct list_head *__ptr = (bond_slave_list(bond)); \ + struct list_head *__next = ACCESS_ONCE(__ptr->next); \ + likely(__ptr != __next) ? \ + list_entry_rcu(__next, struct netdev_adjacent, list)->private : \ + NULL; \ + }) +#define bond_is_first_slave (bond, pos) (pos == bond_first_slave(bond))#define bond_is_last_slave (bond, pos) (pos == bond_last_slave(bond))include/linux/netdevice.h +16
-0@@ -2839,6 +2839,22 @@ extern int netdev_tstamp_prequeue;extern int weight_p;extern int bpf_jit_enable; +struct netdev_adjacent { +struct net_device *dev; + +/* upper master flag, there can only be one master device per list */ +bool master; + +/* 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; +}; +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_all_upper_get_next_dev_rcu(struct net_device *dev,net/core/dev.c +0
-16@@ -4377,22 +4377,6 @@ softnet_break: goto out; } -struct netdev_adjacent { -struct net_device *dev; - -/* upper master flag, there can only be one master device per list */ -bool master; - -/* 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; -}; -static struct netdev_adjacent *__netdev_find_adj_rcu (struct net_device *dev,struct net_device *adj_dev,struct list_head *adj_list)Signature · 1 line
1.8.2.1
Quoted 7 lines · Veaceslav Falico
Quoted 5 lines · Ding Tianhong
The
bond_first_slave_rcu()will be used to instead ofbond_first_slave()inrcu_read_lock().So move the struct
netdev_adjacentto thenetdevice.hand make thebond_first_slave_rcu()could use the struct.
Quoted 7 lines
The whole point in
netdev_adjacentfunctions was to hide it from the users who wanted to use it directly. Seehttp://www.spinics.net/lists/netdev/msg248026.html
for reference. Please try to avoid that.
Hi, Veaceslav
following the point, I rebuild the bond_first_slave_rcu(), if you have no comments, I will move it in the patch set.
Regards
Ding
+/* Caller must have rcu_read_lock */
+#define bond_first_slave_rcu(bond) \
+ netdev_lower_get_first_private_rcu(bond->dev)
+
#define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond)) #define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))
include/linux/netdevice.h +1 -0
@@ -2869,6 +2869,7 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, priv = netdev_lower_get_next_private_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);struct net_device *netdev_master_upper_dev_get_rcu (struct net_device *dev);int netdev_upper_dev_link (struct net_device *dev,struct net_device *upper_dev);
net/core/dev.c +19 -0
@@ -4570,6 +4570,27 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,EXPORT_SYMBOL (netdev_lower_get_next_private_rcu);/** +* netdev_lower_get_first_private_rcu - Get the first ->private from the +* lower neighbour list, RCU +* variant +* @dev: device +* +* Gets the first netdev_adjacent->private from the dev's lower neighbour +* list. The caller must hold RCU read lock. +*/ +void *netdev_lower_get_first_private_rcu (struct net_device *dev) +{ +struct netdev_adjacent *lower; + + lower =list_first_or_null_rcu (&dev->adj_list.lower, + struct netdev_adjacent, list); +if (lower) +return lower->private; +return NULL ; +} +EXPORT_SYMBOL (netdev_lower_get_first_private_rcu);