Hello David,
this is another pull request intended for net-next.
Here you have a batch of patches by Sven Eckelmann that drops our private reference counting implementation and substitutes it with the kref objects/functions.
Then you have a patch, by Simon Wunderlich, that makes the broadcast protection window code more generic so that it can be re-used in the future by other components with different requirements.
Lastly, Sven is also introducing two lockdep asserts in functions operating on our TVLV container list, to make sure that the proper lock is always acquired by the users.
Please pull or let me know of any problem! Thanks a lot, Antonio
The following changes since commit aaa5672052cb0f18a5ab0ab19e9ef71c50e018a8:
sxgbe: remove unused code (2016-02-10 06:10:17 -0500)
are available in the git repository at:
git://git.open-mesh.org/linux-merge.git tags/batman-adv-for-davem
for you to fetch changes up to 92dcdf09a139e51b7b043b9443b8fd69de298dff:
batman-adv: Convert batadv_tt_common_entry to kref (2016-02-10 23:24:06 +0800)
---------------------------------------------------------------- Here you have a batch of patches by Sven Eckelmann that drops our private reference counting implementation and substitutes it with the kref objects/functions.
Then you have a patch, by Simon Wunderlich, that makes the broadcast protection window code more generic so that it can be re-used in the future by other components with different requirements.
Lastly, Sven is also introducing two lockdep asserts in functions operating on our TVLV container list, to make sure that the proper lock is always acquired by the users.
---------------------------------------------------------------- Simon Wunderlich (1): batman-adv: add seqno maximum age and protection start flag parameters
Sven Eckelmann (20): batman-adv: Drop reference to netdevice on last reference batman-adv: Add lockdep assert for container_list_lock batman-adv: Convert batadv_hardif_neigh_node to kref batman-adv: Convert batadv_gw_node to kref batman-adv: Convert batadv_softif_vlan to kref batman-adv: Convert batadv_bla_backbone_gw to kref batman-adv: Convert batadv_bla_claim to kref batman-adv: Convert batadv_nc_node to kref batman-adv: Convert batadv_nc_path to kref batman-adv: Convert batadv_dat_entry to kref batman-adv: Convert batadv_tvlv_container to kref batman-adv: Convert batadv_tvlv_handler to kref batman-adv: Convert batadv_tt_orig_list_entry to kref batman-adv: Convert batadv_neigh_ifinfo to kref batman-adv: Convert batadv_orig_ifinfo to kref batman-adv: Convert batadv_neigh_node to kref batman-adv: Convert batadv_hard_iface to kref batman-adv: Convert batadv_orig_node_vlan to kref batman-adv: Convert batadv_orig_node to kref batman-adv: Convert batadv_tt_common_entry to kref
net/batman-adv/bat_iv_ogm.c | 12 ++-- net/batman-adv/bridge_loop_avoidance.c | 43 +++++++++--- net/batman-adv/distributed-arp-table.c | 29 ++++++-- net/batman-adv/gateway_client.c | 44 ++++++++---- net/batman-adv/hard-interface.c | 25 ++++--- net/batman-adv/hard-interface.h | 16 ++--- net/batman-adv/main.c | 50 +++++++++++--- net/batman-adv/main.h | 3 + net/batman-adv/multicast.c | 7 +- net/batman-adv/network-coding.c | 51 +++++++++----- net/batman-adv/originator.c | 122 ++++++++++++++++++++------------- net/batman-adv/originator.h | 4 +- net/batman-adv/routing.c | 26 ++++--- net/batman-adv/routing.h | 3 +- net/batman-adv/soft-interface.c | 33 ++++++--- net/batman-adv/sysfs.c | 3 +- net/batman-adv/translation-table.c | 90 +++++++++++++++++------- net/batman-adv/types.h | 37 +++++----- 18 files changed, 405 insertions(+), 193 deletions(-)
From: Sven Eckelmann sven@narfation.org
The references to the network device should be dropped inside the release function for batadv_hard_iface similar to what is done with the batman-adv internal datastructures.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/hard-interface.c | 13 ++++++++----- net/batman-adv/hard-interface.h | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index db90022c00a4..b17e272b5cb3 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -47,13 +47,16 @@ #include "sysfs.h" #include "translation-table.h"
-void batadv_hardif_free_rcu(struct rcu_head *rcu) +/** + * batadv_hardif_release - release hard interface from lists and queue for + * free after rcu grace period + * @hard_iface: the hard interface to free + */ +void batadv_hardif_release(struct batadv_hard_iface *hard_iface) { - struct batadv_hard_iface *hard_iface; - - hard_iface = container_of(rcu, struct batadv_hard_iface, rcu); dev_put(hard_iface->net_dev); - kfree(hard_iface); + + kfree_rcu(hard_iface, rcu); }
struct batadv_hard_iface * diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index 4d6b5e12331f..9eb08ad6032d 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h @@ -61,18 +61,18 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface, void batadv_hardif_remove_interfaces(void); int batadv_hardif_min_mtu(struct net_device *soft_iface); void batadv_update_min_mtu(struct net_device *soft_iface); -void batadv_hardif_free_rcu(struct rcu_head *rcu); +void batadv_hardif_release(struct batadv_hard_iface *hard_iface);
/** * batadv_hardif_free_ref - decrement the hard interface refcounter and - * possibly free it + * possibly release it * @hard_iface: the hard interface to free */ static inline void batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) { if (atomic_dec_and_test(&hard_iface->refcount)) - call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); + batadv_hardif_release(hard_iface); }
static inline struct batadv_hard_iface *
From: Simon Wunderlich simon@open-mesh.com
To allow future use of the window protected function with different maximum sequence numbers, add a parameter to set this value which was previously hardcoded. Another parameter added for future use is a flag to return whether the protection window has started.
While at it, also fix the kerneldoc.
Signed-off-by: Simon Wunderlich simon@open-mesh.com Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/bat_iv_ogm.c | 3 ++- net/batman-adv/main.h | 3 +++ net/batman-adv/routing.c | 13 ++++++++++--- net/batman-adv/routing.h | 3 ++- 4 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 3266bcb5bb06..23ce90e21a40 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1315,7 +1315,8 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, /* signalize caller that the packet is to be dropped. */ if (!hlist_empty(&orig_node->neigh_list) && batadv_window_protected(bat_priv, seq_diff, - &orig_ifinfo->batman_seqno_reset)) { + BATADV_TQ_LOCAL_WINDOW_SIZE, + &orig_ifinfo->batman_seqno_reset, NULL)) { ret = BATADV_PROTECTED; goto out; } diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index a7dc41a2709b..32dfc9e578af 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -35,6 +35,9 @@ /* Time To Live of broadcast messages */ #define BATADV_TTL 50
+/* maximum sequence number age of broadcast messages */ +#define BATADV_BCAST_MAX_AGE 64 + /* purge originators after time in seconds if no valid packet comes in * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE */ diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f4b60b1fb50e..1c8b35df50cf 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -146,23 +146,29 @@ out: * @bat_priv: the bat priv with all the soft interface information * @seq_num_diff: difference between the current/received sequence number and * the last sequence number + * @seq_old_max_diff: maximum age of sequence number not considered as restart * @last_reset: jiffies timestamp of the last reset, will be updated when reset * is detected + * @protection_started: is set to true if the protection window was started, + * doesn't change otherwise. * * Return: * 0 if the packet is to be accepted. * 1 if the packet is to be ignored. */ int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff, - unsigned long *last_reset) + s32 seq_old_max_diff, unsigned long *last_reset, + bool *protection_started) { - if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE || + if (seq_num_diff <= -seq_old_max_diff || seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) { if (!batadv_has_timed_out(*last_reset, BATADV_RESET_PROTECTION_MS)) return 1;
*last_reset = jiffies; + if (protection_started) + *protection_started = true; batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "old packet received, start protection\n"); } @@ -1073,7 +1079,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
/* check whether the packet is old and the host just restarted. */ if (batadv_window_protected(bat_priv, seq_diff, - &orig_node->bcast_seqno_reset)) + BATADV_BCAST_MAX_AGE, + &orig_node->bcast_seqno_reset, NULL)) goto spin_unlock;
/* mark broadcast in flood history, update window position diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index c776e9655b9b..02a5caa84127 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h @@ -52,6 +52,7 @@ batadv_find_router(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, struct batadv_hard_iface *recv_if); int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff, - unsigned long *last_reset); + s32 seq_old_max_diff, unsigned long *last_reset, + bool *protection_started);
#endif /* _NET_BATMAN_ADV_ROUTING_H_ */
From: Sven Eckelmann sven@narfation.org
The batadv_tvlv_container* functions state in their kernel-doc that they require tvlv.container_list_lock. Add an assert to automatically detect when this might have been ignored by the caller.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/main.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 5f319fd6ecd7..a9b4f75db874 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -697,6 +697,8 @@ static struct batadv_tvlv_container { struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL;
+ lockdep_assert_held(&bat_priv->tvlv.container_list_lock); + hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) { if (tvlv_tmp->tvlv_hdr.type != type) continue; @@ -729,6 +731,8 @@ static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv) struct batadv_tvlv_container *tvlv; u16 tvlv_len = 0;
+ lockdep_assert_held(&bat_priv->tvlv.container_list_lock); + hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) { tvlv_len += sizeof(struct batadv_tvlv_hdr); tvlv_len += ntohs(tvlv->tvlv_hdr.len);
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/originator.c | 20 ++++++++++++-------- net/batman-adv/types.h | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index d4a30db0158a..7710595ffc42 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -23,6 +23,7 @@ #include <linux/fs.h> #include <linux/jiffies.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> @@ -196,11 +197,15 @@ void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) /** * batadv_hardif_neigh_release - release hardif neigh node from lists and * queue for free after rcu grace period - * @hardif_neigh: hardif neigh neighbor to free + * @ref: kref pointer of the neigh_node */ -static void -batadv_hardif_neigh_release(struct batadv_hardif_neigh_node *hardif_neigh) +static void batadv_hardif_neigh_release(struct kref *ref) { + struct batadv_hardif_neigh_node *hardif_neigh; + + hardif_neigh = container_of(ref, struct batadv_hardif_neigh_node, + refcount); + spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); hlist_del_init_rcu(&hardif_neigh->list); spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); @@ -216,8 +221,7 @@ batadv_hardif_neigh_release(struct batadv_hardif_neigh_node *hardif_neigh) */ void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) { - if (atomic_dec_and_test(&hardif_neigh->refcount)) - batadv_hardif_neigh_release(hardif_neigh); + kref_put(&hardif_neigh->refcount, batadv_hardif_neigh_release); }
/** @@ -529,7 +533,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface, hardif_neigh->if_incoming = hard_iface; hardif_neigh->last_seen = jiffies;
- atomic_set(&hardif_neigh->refcount, 1); + kref_init(&hardif_neigh->refcount);
if (bat_priv->bat_algo_ops->bat_hardif_neigh_init) bat_priv->bat_algo_ops->bat_hardif_neigh_init(hardif_neigh); @@ -584,7 +588,7 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr)) continue;
- if (!atomic_inc_not_zero(&tmp_hardif_neigh->refcount)) + if (!kref_get_unless_zero(&tmp_hardif_neigh->refcount)) continue;
hardif_neigh = tmp_hardif_neigh; @@ -648,7 +652,7 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node, spin_unlock_bh(&orig_node->neigh_list_lock);
/* increment unique neighbor refcount */ - atomic_inc(&hardif_neigh->refcount); + kref_get(&hardif_neigh->refcount);
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, "Creating new neighbor %pM for orig_node %pM on interface %s\n", diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 8974bc0dc15c..ace7900347d4 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -25,6 +25,7 @@ #include <linux/bitops.h> #include <linux/compiler.h> #include <linux/if_ether.h> +#include <linux/kref.h> #include <linux/netdevice.h> #include <linux/sched.h> /* for linux/wait.h */ #include <linux/spinlock.h> @@ -359,7 +360,7 @@ struct batadv_hardif_neigh_node { u8 addr[ETH_ALEN]; struct batadv_hard_iface *if_incoming; unsigned long last_seen; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/gateway_client.c | 40 +++++++++++++++++++++++++++++----------- net/batman-adv/types.h | 2 +- 2 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 5950974de7b1..1f3847c61db8 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -28,6 +28,7 @@ #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/netdevice.h> #include <linux/rculist.h> @@ -59,12 +60,29 @@ */ #define BATADV_DHCP_CHADDR_OFFSET 28
+/** + * batadv_gw_node_release - release gw_node from lists and queue for free after + * rcu grace period + * @ref: kref pointer of the gw_node + */ +static void batadv_gw_node_release(struct kref *ref) +{ + struct batadv_gw_node *gw_node; + + gw_node = container_of(ref, struct batadv_gw_node, refcount); + + batadv_orig_node_free_ref(gw_node->orig_node); + kfree_rcu(gw_node, rcu); +} + +/** + * batadv_gw_node_free_ref - decrement the gw_node refcounter and possibly + * release it + * @gw_node: gateway node to free + */ static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) { - if (atomic_dec_and_test(&gw_node->refcount)) { - batadv_orig_node_free_ref(gw_node->orig_node); - kfree_rcu(gw_node, rcu); - } + kref_put(&gw_node->refcount, batadv_gw_node_release); }
static struct batadv_gw_node * @@ -77,7 +95,7 @@ batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv) if (!gw_node) goto out;
- if (!atomic_inc_not_zero(&gw_node->refcount)) + if (!kref_get_unless_zero(&gw_node->refcount)) gw_node = NULL;
out: @@ -118,7 +136,7 @@ static void batadv_gw_select(struct batadv_priv *bat_priv,
spin_lock_bh(&bat_priv->gw.list_lock);
- if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) + if (new_gw_node && !kref_get_unless_zero(&new_gw_node->refcount)) new_gw_node = NULL;
curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1); @@ -170,7 +188,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) if (!router_ifinfo) goto next;
- if (!atomic_inc_not_zero(&gw_node->refcount)) + if (!kref_get_unless_zero(&gw_node->refcount)) goto next;
tq_avg = router_ifinfo->bat_iv.tq_avg; @@ -188,7 +206,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) if (curr_gw) batadv_gw_node_free_ref(curr_gw); curr_gw = gw_node; - atomic_inc(&curr_gw->refcount); + kref_get(&curr_gw->refcount); } break;
@@ -203,7 +221,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) if (curr_gw) batadv_gw_node_free_ref(curr_gw); curr_gw = gw_node; - atomic_inc(&curr_gw->refcount); + kref_get(&curr_gw->refcount); } break; } @@ -436,7 +454,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, gw_node->orig_node = orig_node; gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); - atomic_set(&gw_node->refcount, 1); + kref_init(&gw_node->refcount);
spin_lock_bh(&bat_priv->gw.list_lock); hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); @@ -469,7 +487,7 @@ batadv_gw_node_get(struct batadv_priv *bat_priv, if (gw_node_tmp->orig_node != orig_node) continue;
- if (!atomic_inc_not_zero(&gw_node_tmp->refcount)) + if (!kref_get_unless_zero(&gw_node_tmp->refcount)) continue;
gw_node = gw_node_tmp; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index ace7900347d4..06c38881e382 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -342,7 +342,7 @@ struct batadv_gw_node { struct batadv_orig_node *orig_node; u32 bandwidth_down; u32 bandwidth_up; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/soft-interface.c | 33 +++++++++++++++++++++++---------- net/batman-adv/sysfs.c | 3 ++- net/batman-adv/types.h | 2 +- 3 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 4bf35b8c3d23..d4490ff75edd 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -30,6 +30,7 @@ #include <linux/if_vlan.h> #include <linux/jiffies.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> @@ -478,8 +479,26 @@ out: }
/** + * batadv_softif_vlan_release - release vlan from lists and queue for free after + * rcu grace period + * @ref: kref pointer of the vlan object + */ +static void batadv_softif_vlan_release(struct kref *ref) +{ + struct batadv_softif_vlan *vlan; + + vlan = container_of(ref, struct batadv_softif_vlan, refcount); + + spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); + hlist_del_rcu(&vlan->list); + spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock); + + kfree_rcu(vlan, rcu); +} + +/** * batadv_softif_vlan_free_ref - decrease the vlan object refcounter and - * possibly free it + * possibly release it * @vlan: the vlan object to release */ void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) @@ -487,13 +506,7 @@ void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) if (!vlan) return;
- if (atomic_dec_and_test(&vlan->refcount)) { - spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); - hlist_del_rcu(&vlan->list); - spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock); - - kfree_rcu(vlan, rcu); - } + kref_put(&vlan->refcount, batadv_softif_vlan_release); }
/** @@ -514,7 +527,7 @@ struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv, if (vlan_tmp->vid != vid) continue;
- if (!atomic_inc_not_zero(&vlan_tmp->refcount)) + if (!kref_get_unless_zero(&vlan_tmp->refcount)) continue;
vlan = vlan_tmp; @@ -549,7 +562,7 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
vlan->bat_priv = bat_priv; vlan->vid = vid; - atomic_set(&vlan->refcount, 1); + kref_init(&vlan->refcount);
atomic_set(&vlan->ap_isolation, 0);
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 964fc5986b2c..ab4382ba3855 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -25,6 +25,7 @@ #include <linux/fs.h> #include <linux/if.h> #include <linux/if_vlan.h> +#include <linux/kref.h> #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/printk.h> @@ -97,7 +98,7 @@ batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj) if (vlan_tmp->kobj != obj) continue;
- if (!atomic_inc_not_zero(&vlan_tmp->refcount)) + if (!kref_get_unless_zero(&vlan_tmp->refcount)) continue;
vlan = vlan_tmp; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 06c38881e382..868f6b592b7c 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -746,7 +746,7 @@ struct batadv_softif_vlan { atomic_t ap_isolation; /* boolean */ struct batadv_vlan_tt tt; struct hlist_node list; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/bridge_loop_avoidance.c | 29 +++++++++++++++++++++++------ net/batman-adv/types.h | 2 +- 2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 779160934844..41116e4c2e34 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -31,6 +31,7 @@ #include <linux/jhash.h> #include <linux/jiffies.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> @@ -143,14 +144,29 @@ static int batadv_compare_claim(const struct hlist_node *node, }
/** - * batadv_compare_backbone_gw - free backbone gw + * batadv_backbone_gw_release - release backbone gw from lists and queue for + * free after rcu grace period + * @ref: kref pointer of the backbone gw + */ +static void batadv_backbone_gw_release(struct kref *ref) +{ + struct batadv_bla_backbone_gw *backbone_gw; + + backbone_gw = container_of(ref, struct batadv_bla_backbone_gw, + refcount); + + kfree_rcu(backbone_gw, rcu); +} + +/** + * batadv_backbone_gw_free_ref - decrement the backbone gw refcounter and + * possibly release it * @backbone_gw: backbone gateway to be free'd */ static void batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw) { - if (atomic_dec_and_test(&backbone_gw->refcount)) - kfree_rcu(backbone_gw, rcu); + kref_put(&backbone_gw->refcount, batadv_backbone_gw_release); }
/** @@ -247,7 +263,7 @@ batadv_backbone_hash_find(struct batadv_priv *bat_priv, u8 *addr, &search_entry)) continue;
- if (!atomic_inc_not_zero(&backbone_gw->refcount)) + if (!kref_get_unless_zero(&backbone_gw->refcount)) continue;
backbone_gw_tmp = backbone_gw; @@ -448,7 +464,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig, ether_addr_copy(entry->orig, orig);
/* one for the hash, one for returning */ - atomic_set(&entry->refcount, 2); + kref_init(&entry->refcount); + kref_get(&entry->refcount);
hash_added = batadv_hash_add(bat_priv->bla.backbone_hash, batadv_compare_backbone_gw, @@ -664,7 +681,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, batadv_backbone_gw_free_ref(claim->backbone_gw); } /* set (new) backbone gw */ - atomic_inc(&backbone_gw->refcount); + kref_get(&backbone_gw->refcount); claim->backbone_gw = backbone_gw;
spin_lock_bh(&backbone_gw->crc_lock); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 868f6b592b7c..595f52400b1f 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -930,7 +930,7 @@ struct batadv_bla_backbone_gw { atomic_t request_sent; u16 crc; spinlock_t crc_lock; /* protects crc */ - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/bridge_loop_avoidance.c | 14 +++++++++----- net/batman-adv/types.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 41116e4c2e34..7781f39c174d 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -174,8 +174,12 @@ batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw) * grace period * @ref: kref pointer of the claim */ -static void batadv_claim_release(struct batadv_bla_claim *claim) +static void batadv_claim_release(struct kref *ref) { + struct batadv_bla_claim *claim; + + claim = container_of(ref, struct batadv_bla_claim, refcount); + batadv_backbone_gw_free_ref(claim->backbone_gw); kfree_rcu(claim, rcu); } @@ -187,8 +191,7 @@ static void batadv_claim_release(struct batadv_bla_claim *claim) */ static void batadv_claim_free_ref(struct batadv_bla_claim *claim) { - if (atomic_dec_and_test(&claim->refcount)) - batadv_claim_release(claim); + kref_put(&claim->refcount, batadv_claim_release); }
/** @@ -219,7 +222,7 @@ static struct batadv_bla_claim if (!batadv_compare_claim(&claim->hash_entry, data)) continue;
- if (!atomic_inc_not_zero(&claim->refcount)) + if (!kref_get_unless_zero(&claim->refcount)) continue;
claim_tmp = claim; @@ -651,7 +654,8 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, claim->lasttime = jiffies; claim->backbone_gw = backbone_gw;
- atomic_set(&claim->refcount, 2); + kref_init(&claim->refcount); + kref_get(&claim->refcount); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n", mac, BATADV_PRINT_VID(vid)); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 595f52400b1f..34c13b65bec2 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -951,7 +951,7 @@ struct batadv_bla_claim { unsigned long lasttime; struct hlist_node hash_entry; struct rcu_head rcu; - atomic_t refcount; + struct kref refcount; }; #endif
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/network-coding.c | 21 +++++++++++++-------- net/batman-adv/types.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 0b30c15eee5f..7a1216eeb4cf 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -32,6 +32,7 @@ #include <linux/jhash.h> #include <linux/jiffies.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> @@ -209,23 +210,26 @@ void batadv_nc_init_orig(struct batadv_orig_node *orig_node) /** * batadv_nc_node_release - release nc_node from lists and queue for free after * rcu grace period - * @nc_node: the nc node to free + * @ref: kref pointer of the nc_node */ -static void batadv_nc_node_release(struct batadv_nc_node *nc_node) +static void batadv_nc_node_release(struct kref *ref) { + struct batadv_nc_node *nc_node; + + nc_node = container_of(ref, struct batadv_nc_node, refcount); + batadv_orig_node_free_ref(nc_node->orig_node); kfree_rcu(nc_node, rcu); }
/** - * batadv_nc_node_free_ref - decrement the nc node refcounter and possibly + * batadv_nc_node_free_ref - decrement the nc_node refcounter and possibly * release it - * @nc_node: the nc node to free + * @nc_node: nc_node to be free'd */ static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) { - if (atomic_dec_and_test(&nc_node->refcount)) - batadv_nc_node_release(nc_node); + kref_put(&nc_node->refcount, batadv_nc_node_release); }
/** @@ -797,7 +801,7 @@ static struct batadv_nc_node if (!batadv_compare_eth(nc_node->addr, orig_node->orig)) continue;
- if (!atomic_inc_not_zero(&nc_node->refcount)) + if (!kref_get_unless_zero(&nc_node->refcount)) continue;
/* Found a match */ @@ -848,7 +852,8 @@ static struct batadv_nc_node INIT_LIST_HEAD(&nc_node->list); ether_addr_copy(nc_node->addr, orig_node->orig); nc_node->orig_node = orig_neigh_node; - atomic_set(&nc_node->refcount, 2); + kref_init(&nc_node->refcount); + kref_get(&nc_node->refcount);
/* Select ingoing or outgoing coding node */ if (in_coding) { diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 34c13b65bec2..05421afb1d74 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1067,7 +1067,7 @@ struct batadv_tt_roam_node { struct batadv_nc_node { struct list_head list; u8 addr[ETH_ALEN]; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; struct batadv_orig_node *orig_node; unsigned long last_seen;
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/network-coding.c | 28 +++++++++++++++++++++------- net/batman-adv/types.h | 2 +- 2 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 7a1216eeb4cf..371fc6bbf9d6 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -233,14 +233,27 @@ static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) }
/** - * batadv_nc_path_free_ref - decrements the nc path refcounter and possibly - * frees it - * @nc_path: the nc node to free + * batadv_nc_path_release - release nc_path from lists and queue for free after + * rcu grace period + * @ref: kref pointer of the nc_path + */ +static void batadv_nc_path_release(struct kref *ref) +{ + struct batadv_nc_path *nc_path; + + nc_path = container_of(ref, struct batadv_nc_path, refcount); + + kfree_rcu(nc_path, rcu); +} + +/** + * batadv_nc_path_free_ref - decrement the nc_path refcounter and possibly + * release it + * @nc_path: nc_path to be free'd */ static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path) { - if (atomic_dec_and_test(&nc_path->refcount)) - kfree_rcu(nc_path, rcu); + kref_put(&nc_path->refcount, batadv_nc_path_release); }
/** @@ -545,7 +558,7 @@ batadv_nc_hash_find(struct batadv_hashtable *hash, if (!batadv_nc_hash_compare(&nc_path->hash_entry, data)) continue;
- if (!atomic_inc_not_zero(&nc_path->refcount)) + if (!kref_get_unless_zero(&nc_path->refcount)) continue;
nc_path_tmp = nc_path; @@ -972,7 +985,8 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, /* Initialize nc_path */ INIT_LIST_HEAD(&nc_path->packet_list); spin_lock_init(&nc_path->packet_list_lock); - atomic_set(&nc_path->refcount, 2); + kref_init(&nc_path->refcount); + kref_get(&nc_path->refcount); nc_path->last_valid = jiffies; ether_addr_copy(nc_path->next_hop, dst); ether_addr_copy(nc_path->prev_hop, src); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 05421afb1d74..b3d9b5b566a2 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1087,7 +1087,7 @@ struct batadv_nc_node { struct batadv_nc_path { struct hlist_node hash_entry; struct rcu_head rcu; - atomic_t refcount; + struct kref refcount; struct list_head packet_list; spinlock_t packet_list_lock; /* Protects packet_list */ u8 next_hop[ETH_ALEN];
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/distributed-arp-table.c | 27 +++++++++++++++++++++------ net/batman-adv/types.h | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 017fffe9a5b8..921e25255cab 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -30,6 +30,7 @@ #include <linux/in.h> #include <linux/jiffies.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/rculist.h> #include <linux/rcupdate.h> @@ -62,14 +63,27 @@ static void batadv_dat_start_timer(struct batadv_priv *bat_priv) }
/** + * batadv_dat_entry_release - release dat_entry from lists and queue for free + * after rcu grace period + * @ref: kref pointer of the dat_entry + */ +static void batadv_dat_entry_release(struct kref *ref) +{ + struct batadv_dat_entry *dat_entry; + + dat_entry = container_of(ref, struct batadv_dat_entry, refcount); + + kfree_rcu(dat_entry, rcu); +} + +/** * batadv_dat_entry_free_ref - decrement the dat_entry refcounter and possibly - * free it - * @dat_entry: the entry to free + * release it + * @dat_entry: dat_entry to be free'd */ static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry) { - if (atomic_dec_and_test(&dat_entry->refcount)) - kfree_rcu(dat_entry, rcu); + kref_put(&dat_entry->refcount, batadv_dat_entry_release); }
/** @@ -281,7 +295,7 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip, if (dat_entry->ip != ip) continue;
- if (!atomic_inc_not_zero(&dat_entry->refcount)) + if (!kref_get_unless_zero(&dat_entry->refcount)) continue;
dat_entry_tmp = dat_entry; @@ -326,7 +340,8 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip, dat_entry->vid = vid; ether_addr_copy(dat_entry->mac_addr, mac_addr); dat_entry->last_update = jiffies; - atomic_set(&dat_entry->refcount, 2); + kref_init(&dat_entry->refcount); + kref_get(&dat_entry->refcount);
hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat, batadv_hash_dat, dat_entry, diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index b3d9b5b566a2..9df8f39e4785 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1230,7 +1230,7 @@ struct batadv_dat_entry { unsigned short vid; unsigned long last_update; struct hlist_node hash_entry; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/main.c | 22 +++++++++++++++++----- net/batman-adv/types.h | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index a9b4f75db874..4b6c2589fa34 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -29,6 +29,7 @@ #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/module.h> @@ -670,14 +671,25 @@ static struct batadv_tvlv_handler }
/** + * batadv_tvlv_container_release - release tvlv from lists and free + * @ref: kref pointer of the tvlv + */ +static void batadv_tvlv_container_release(struct kref *ref) +{ + struct batadv_tvlv_container *tvlv; + + tvlv = container_of(ref, struct batadv_tvlv_container, refcount); + kfree(tvlv); +} + +/** * batadv_tvlv_container_free_ref - decrement the tvlv container refcounter and - * possibly free it + * possibly release it * @tvlv: the tvlv container to free */ static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv) { - if (atomic_dec_and_test(&tvlv->refcount)) - kfree(tvlv); + kref_put(&tvlv->refcount, batadv_tvlv_container_release); }
/** @@ -706,7 +718,7 @@ static struct batadv_tvlv_container if (tvlv_tmp->tvlv_hdr.version != version) continue;
- if (!atomic_inc_not_zero(&tvlv_tmp->refcount)) + if (!kref_get_unless_zero(&tvlv_tmp->refcount)) continue;
tvlv = tvlv_tmp; @@ -814,7 +826,7 @@ void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len)); INIT_HLIST_NODE(&tvlv_new->list); - atomic_set(&tvlv_new->refcount, 1); + kref_init(&tvlv_new->refcount);
spin_lock_bh(&bat_priv->tvlv.container_list_lock); tvlv_old = batadv_tvlv_container_get(bat_priv, type, version); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 9df8f39e4785..c55925bb34af 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1266,7 +1266,7 @@ struct batadv_dat_candidate { struct batadv_tvlv_container { struct hlist_node list; struct batadv_tvlv_hdr tvlv_hdr; - atomic_t refcount; + struct kref refcount; };
/**
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/main.c | 24 ++++++++++++++++++------ net/batman-adv/types.h | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 4b6c2589fa34..568c5503f637 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -625,15 +625,27 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr) }
/** - * batadv_tvlv_handler_free_ref - decrement the tvlv handler refcounter and - * possibly free it + * batadv_tvlv_handler_release - release tvlv handler from lists and queue for + * free after rcu grace period + * @ref: kref pointer of the tvlv + */ +static void batadv_tvlv_handler_release(struct kref *ref) +{ + struct batadv_tvlv_handler *tvlv_handler; + + tvlv_handler = container_of(ref, struct batadv_tvlv_handler, refcount); + kfree_rcu(tvlv_handler, rcu); +} + +/** + * batadv_tvlv_handler_free_ref - decrement the tvlv container refcounter and + * possibly release it * @tvlv_handler: the tvlv handler to free */ static void batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler) { - if (atomic_dec_and_test(&tvlv_handler->refcount)) - kfree_rcu(tvlv_handler, rcu); + kref_put(&tvlv_handler->refcount, batadv_tvlv_handler_release); }
/** @@ -659,7 +671,7 @@ static struct batadv_tvlv_handler if (tvlv_handler_tmp->version != version) continue;
- if (!atomic_inc_not_zero(&tvlv_handler_tmp->refcount)) + if (!kref_get_unless_zero(&tvlv_handler_tmp->refcount)) continue;
tvlv_handler = tvlv_handler_tmp; @@ -1112,7 +1124,7 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, tvlv_handler->type = type; tvlv_handler->version = version; tvlv_handler->flags = flags; - atomic_set(&tvlv_handler->refcount, 1); + kref_init(&tvlv_handler->refcount); INIT_HLIST_NODE(&tvlv_handler->list);
spin_lock_bh(&bat_priv->tvlv.handler_list_lock); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index c55925bb34af..f89dd977f348 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1293,7 +1293,7 @@ struct batadv_tvlv_handler { u8 type; u8 version; u8 flags; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/translation-table.c | 26 +++++++++++++++++--------- net/batman-adv/types.h | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 0dc8a5ca33bf..68494a10848c 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -31,6 +31,7 @@ #include <linux/jhash.h> #include <linux/jiffies.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> @@ -346,22 +347,28 @@ static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node, /** * batadv_tt_orig_list_entry_release - release tt orig entry from lists and * queue for free after rcu grace period - * @orig_entry: tt orig entry to be free'd + * @ref: kref pointer of the tt orig entry */ -static void -batadv_tt_orig_list_entry_release(struct batadv_tt_orig_list_entry *orig_entry) +static void batadv_tt_orig_list_entry_release(struct kref *ref) { + struct batadv_tt_orig_list_entry *orig_entry; + + orig_entry = container_of(ref, struct batadv_tt_orig_list_entry, + refcount); + batadv_orig_node_free_ref(orig_entry->orig_node); kfree_rcu(orig_entry, rcu); }
+/** + * batadv_tt_orig_list_entry_free_ref - decrement the tt orig entry refcounter + * and possibly release it + * @orig_entry: tt orig entry to be free'd + */ static void batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) { - if (!atomic_dec_and_test(&orig_entry->refcount)) - return; - - batadv_tt_orig_list_entry_release(orig_entry); + kref_put(&orig_entry->refcount, batadv_tt_orig_list_entry_release); }
/** @@ -1270,7 +1277,7 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, hlist_for_each_entry_rcu(tmp_orig_entry, head, list) { if (tmp_orig_entry->orig_node != orig_node) continue; - if (!atomic_inc_not_zero(&tmp_orig_entry->refcount)) + if (!kref_get_unless_zero(&tmp_orig_entry->refcount)) continue;
orig_entry = tmp_orig_entry; @@ -1331,7 +1338,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, batadv_tt_global_size_inc(orig_node, tt_global->common.vid); orig_entry->orig_node = orig_node; orig_entry->ttvn = ttvn; - atomic_set(&orig_entry->refcount, 2); + kref_init(&orig_entry->refcount); + kref_get(&orig_entry->refcount);
spin_lock_bh(&tt_global->list_lock); hlist_add_head_rcu(&orig_entry->list, diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index f89dd977f348..17f97ff5b4d1 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1014,7 +1014,7 @@ struct batadv_tt_orig_list_entry { struct batadv_orig_node *orig_node; u8 ttvn; struct hlist_node list; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/originator.c | 17 ++++++++++------- net/batman-adv/types.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 7710595ffc42..1c50abe52c6d 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -172,11 +172,14 @@ err: /** * batadv_neigh_ifinfo_release - release neigh_ifinfo from lists and queue for * free after rcu grace period - * @neigh_ifinfo: the neigh_ifinfo object to release + * @ref: kref pointer of the neigh_ifinfo */ -static void -batadv_neigh_ifinfo_release(struct batadv_neigh_ifinfo *neigh_ifinfo) +static void batadv_neigh_ifinfo_release(struct kref *ref) { + struct batadv_neigh_ifinfo *neigh_ifinfo; + + neigh_ifinfo = container_of(ref, struct batadv_neigh_ifinfo, refcount); + if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) batadv_hardif_free_ref(neigh_ifinfo->if_outgoing);
@@ -190,8 +193,7 @@ batadv_neigh_ifinfo_release(struct batadv_neigh_ifinfo *neigh_ifinfo) */ void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) { - if (atomic_dec_and_test(&neigh_ifinfo->refcount)) - batadv_neigh_ifinfo_release(neigh_ifinfo); + kref_put(&neigh_ifinfo->refcount, batadv_neigh_ifinfo_release); }
/** @@ -405,7 +407,7 @@ batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, if (tmp_neigh_ifinfo->if_outgoing != if_outgoing) continue;
- if (!atomic_inc_not_zero(&tmp_neigh_ifinfo->refcount)) + if (!kref_get_unless_zero(&tmp_neigh_ifinfo->refcount)) continue;
neigh_ifinfo = tmp_neigh_ifinfo; @@ -450,7 +452,8 @@ batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, }
INIT_HLIST_NODE(&neigh_ifinfo->list); - atomic_set(&neigh_ifinfo->refcount, 2); + kref_init(&neigh_ifinfo->refcount); + kref_get(&neigh_ifinfo->refcount); neigh_ifinfo->if_outgoing = if_outgoing;
hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 17f97ff5b4d1..81d9f8d6c54b 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -420,7 +420,7 @@ struct batadv_neigh_ifinfo { struct batadv_hard_iface *if_outgoing; struct batadv_neigh_ifinfo_bat_iv bat_iv; u8 last_ttl; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/originator.c | 15 +++++++++------ net/batman-adv/routing.c | 5 +++-- net/batman-adv/types.h | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 1c50abe52c6d..428983a2036f 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -326,7 +326,7 @@ batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, if (tmp->if_outgoing != if_outgoing) continue;
- if (!atomic_inc_not_zero(&tmp->refcount)) + if (!kref_get_unless_zero(&tmp->refcount)) continue;
orig_ifinfo = tmp; @@ -377,7 +377,8 @@ batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node, orig_ifinfo->batman_seqno_reset = reset_time; orig_ifinfo->if_outgoing = if_outgoing; INIT_HLIST_NODE(&orig_ifinfo->list); - atomic_set(&orig_ifinfo->refcount, 2); + kref_init(&orig_ifinfo->refcount); + kref_get(&orig_ifinfo->refcount); hlist_add_head_rcu(&orig_ifinfo->list, &orig_node->ifinfo_list); out: @@ -704,12 +705,15 @@ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset) /** * batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for * free after rcu grace period - * @orig_ifinfo: the orig_ifinfo object to release + * @ref: kref pointer of the orig_ifinfo */ -static void batadv_orig_ifinfo_release(struct batadv_orig_ifinfo *orig_ifinfo) +static void batadv_orig_ifinfo_release(struct kref *ref) { + struct batadv_orig_ifinfo *orig_ifinfo; struct batadv_neigh_node *router;
+ orig_ifinfo = container_of(ref, struct batadv_orig_ifinfo, refcount); + if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) batadv_hardif_free_ref(orig_ifinfo->if_outgoing);
@@ -728,8 +732,7 @@ static void batadv_orig_ifinfo_release(struct batadv_orig_ifinfo *orig_ifinfo) */ void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo) { - if (atomic_dec_and_test(&orig_ifinfo->refcount)) - batadv_orig_ifinfo_release(orig_ifinfo); + kref_put(&orig_ifinfo->refcount, batadv_orig_ifinfo_release); }
/** diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 1c8b35df50cf..4a5cd8bf2661 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -25,6 +25,7 @@ #include <linux/etherdevice.h> #include <linux/if_ether.h> #include <linux/jiffies.h> +#include <linux/kref.h> #include <linux/netdevice.h> #include <linux/printk.h> #include <linux/rculist.h> @@ -497,7 +498,7 @@ batadv_find_router(struct batadv_priv *bat_priv,
hlist_for_each_entry_rcu(cand, &orig_node->ifinfo_list, list) { /* acquire some structures and references ... */ - if (!atomic_inc_not_zero(&cand->refcount)) + if (!kref_get_unless_zero(&cand->refcount)) continue;
cand_router = rcu_dereference(cand->router); @@ -524,7 +525,7 @@ batadv_find_router(struct batadv_priv *bat_priv, /* mark the first possible candidate */ if (!first_candidate) { atomic_inc(&cand_router->refcount); - atomic_inc(&cand->refcount); + kref_get(&cand->refcount); first_candidate = cand; first_candidate_router = cand_router; } diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 81d9f8d6c54b..6193c01b47d2 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -141,7 +141,7 @@ struct batadv_orig_ifinfo { u32 last_real_seqno; u8 last_ttl; unsigned long batman_seqno_reset; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/bat_iv_ogm.c | 5 +++-- net/batman-adv/originator.c | 22 ++++++++++++---------- net/batman-adv/routing.c | 8 ++++---- net/batman-adv/types.h | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 23ce90e21a40..affcbb571426 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -31,6 +31,7 @@ #include <linux/init.h> #include <linux/jiffies.h> #include <linux/list.h> +#include <linux/kref.h> #include <linux/netdevice.h> #include <linux/pkt_sched.h> #include <linux/printk.h> @@ -1002,7 +1003,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, neigh_addr = tmp_neigh_node->addr; if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && tmp_neigh_node->if_incoming == if_incoming && - atomic_inc_not_zero(&tmp_neigh_node->refcount)) { + kref_get_unless_zero(&tmp_neigh_node->refcount)) { if (WARN(neigh_node, "too many matching neigh_nodes")) batadv_neigh_node_free_ref(neigh_node); neigh_node = tmp_neigh_node; @@ -1161,7 +1162,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, if (tmp_neigh_node->if_incoming != if_incoming) continue;
- if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + if (!kref_get_unless_zero(&tmp_neigh_node->refcount)) continue;
neigh_node = tmp_neigh_node; diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 428983a2036f..9e3dbd88c69e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -229,15 +229,17 @@ void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) /** * batadv_neigh_node_release - release neigh_node from lists and queue for * free after rcu grace period - * @neigh_node: neigh neighbor to free + * @ref: kref pointer of the neigh_node */ -static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node) +static void batadv_neigh_node_release(struct kref *ref) { struct hlist_node *node_tmp; + struct batadv_neigh_node *neigh_node; struct batadv_hardif_neigh_node *hardif_neigh; struct batadv_neigh_ifinfo *neigh_ifinfo; struct batadv_algo_ops *bao;
+ neigh_node = container_of(ref, struct batadv_neigh_node, refcount); bao = neigh_node->orig_node->bat_priv->bat_algo_ops;
hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, @@ -262,14 +264,13 @@ static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node) }
/** - * batadv_neigh_node_free_ref - decrement the neighbors refcounter - * and possibly release it + * batadv_neigh_node_free_ref - decrement the neighbors refcounter and possibly + * release it * @neigh_node: neigh neighbor to free */ void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) { - if (atomic_dec_and_test(&neigh_node->refcount)) - batadv_neigh_node_release(neigh_node); + kref_put(&neigh_node->refcount, batadv_neigh_node_release); }
/** @@ -298,7 +299,7 @@ batadv_orig_router_get(struct batadv_orig_node *orig_node, break; }
- if (router && !atomic_inc_not_zero(&router->refcount)) + if (router && !kref_get_unless_zero(&router->refcount)) router = NULL;
rcu_read_unlock(); @@ -491,7 +492,7 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node, if (tmp_neigh_node->if_incoming != hard_iface) continue;
- if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + if (!kref_get_unless_zero(&tmp_neigh_node->refcount)) continue;
res = tmp_neigh_node; @@ -649,7 +650,8 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node, neigh_node->orig_node = orig_node;
/* extra reference for return */ - atomic_set(&neigh_node->refcount, 2); + kref_init(&neigh_node->refcount); + kref_get(&neigh_node->refcount);
spin_lock_bh(&orig_node->neigh_list_lock); hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); @@ -1084,7 +1086,7 @@ batadv_find_best_neighbor(struct batadv_priv *bat_priv, best, if_outgoing) <= 0)) continue;
- if (!atomic_inc_not_zero(&neigh->refcount)) + if (!kref_get_unless_zero(&neigh->refcount)) continue;
if (best) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 4a5cd8bf2661..205310b56c2b 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -73,7 +73,7 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
rcu_read_lock(); curr_router = rcu_dereference(orig_ifinfo->router); - if (curr_router && !atomic_inc_not_zero(&curr_router->refcount)) + if (curr_router && !kref_get_unless_zero(&curr_router->refcount)) curr_router = NULL; rcu_read_unlock();
@@ -101,7 +101,7 @@ static void _batadv_update_route(struct batadv_priv *bat_priv, batadv_neigh_node_free_ref(curr_router);
/* increase refcount of new best neighbor */ - if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) + if (neigh_node && !kref_get_unless_zero(&neigh_node->refcount)) neigh_node = NULL;
spin_lock_bh(&orig_node->neigh_list_lock); @@ -505,7 +505,7 @@ batadv_find_router(struct batadv_priv *bat_priv, if (!cand_router) goto next;
- if (!atomic_inc_not_zero(&cand_router->refcount)) { + if (!kref_get_unless_zero(&cand_router->refcount)) { cand_router = NULL; goto next; } @@ -524,7 +524,7 @@ batadv_find_router(struct batadv_priv *bat_priv,
/* mark the first possible candidate */ if (!first_candidate) { - atomic_inc(&cand_router->refcount); + kref_get(&cand_router->refcount); kref_get(&cand->refcount); first_candidate = cand; first_candidate_router = cand_router; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 6193c01b47d2..68ca39e1713d 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -384,7 +384,7 @@ struct batadv_neigh_node { spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */ struct batadv_hard_iface *if_incoming; unsigned long last_seen; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/bat_iv_ogm.c | 4 ++-- net/batman-adv/hard-interface.c | 20 +++++++++++++------- net/batman-adv/hard-interface.h | 16 +++++++--------- net/batman-adv/originator.c | 8 ++++---- net/batman-adv/types.h | 2 +- 5 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index affcbb571426..bf0e7d6f12bb 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -644,10 +644,10 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, unsigned char *skb_buff; unsigned int skb_size;
- if (!atomic_inc_not_zero(&if_incoming->refcount)) + if (!kref_get_unless_zero(&if_incoming->refcount)) return;
- if (!atomic_inc_not_zero(&if_outgoing->refcount)) + if (!kref_get_unless_zero(&if_outgoing->refcount)) goto out_free_incoming;
/* own packet should always be scheduled */ diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b17e272b5cb3..fb2d9c058ed0 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -18,6 +18,7 @@ #include "hard-interface.h" #include "main.h"
+#include <linux/atomic.h> #include <linux/bug.h> #include <linux/byteorder/generic.h> #include <linux/errno.h> @@ -26,6 +27,7 @@ #include <linux/if_ether.h> #include <linux/if.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/netdevice.h> #include <linux/printk.h> @@ -50,10 +52,13 @@ /** * batadv_hardif_release - release hard interface from lists and queue for * free after rcu grace period - * @hard_iface: the hard interface to free + * @ref: kref pointer of the hard interface */ -void batadv_hardif_release(struct batadv_hard_iface *hard_iface) +void batadv_hardif_release(struct kref *ref) { + struct batadv_hard_iface *hard_iface; + + hard_iface = container_of(ref, struct batadv_hard_iface, refcount); dev_put(hard_iface->net_dev);
kfree_rcu(hard_iface, rcu); @@ -67,7 +72,7 @@ batadv_hardif_get_by_netdev(const struct net_device *net_dev) rcu_read_lock(); list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { if (hard_iface->net_dev == net_dev && - atomic_inc_not_zero(&hard_iface->refcount)) + kref_get_unless_zero(&hard_iface->refcount)) goto out; }
@@ -172,7 +177,7 @@ batadv_hardif_get_active(const struct net_device *soft_iface) continue;
if (hard_iface->if_status == BATADV_IF_ACTIVE && - atomic_inc_not_zero(&hard_iface->refcount)) + kref_get_unless_zero(&hard_iface->refcount)) goto out; }
@@ -206,7 +211,7 @@ static void batadv_primary_if_select(struct batadv_priv *bat_priv,
ASSERT_RTNL();
- if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) + if (new_hard_iface && !kref_get_unless_zero(&new_hard_iface->refcount)) new_hard_iface = NULL;
curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1); @@ -434,7 +439,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) goto out;
- if (!atomic_inc_not_zero(&hard_iface->refcount)) + if (!kref_get_unless_zero(&hard_iface->refcount)) goto out;
soft_iface = dev_get_by_name(&init_net, iface_name); @@ -655,7 +660,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
/* extra reference for return */ - atomic_set(&hard_iface->refcount, 2); + kref_init(&hard_iface->refcount); + kref_get(&hard_iface->refcount);
batadv_check_known_mac_addr(hard_iface->net_dev); list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index 9eb08ad6032d..5cecc6bc1b1e 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h @@ -20,8 +20,8 @@
#include "main.h"
-#include <linux/atomic.h> #include <linux/compiler.h> +#include <linux/kref.h> #include <linux/notifier.h> #include <linux/rcupdate.h> #include <linux/stddef.h> @@ -61,18 +61,16 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface, void batadv_hardif_remove_interfaces(void); int batadv_hardif_min_mtu(struct net_device *soft_iface); void batadv_update_min_mtu(struct net_device *soft_iface); -void batadv_hardif_release(struct batadv_hard_iface *hard_iface); +void batadv_hardif_release(struct kref *ref);
/** - * batadv_hardif_free_ref - decrement the hard interface refcounter and - * possibly release it + * batadv_hardif_free_ref - decrement the hard interface refcounter and possibly + * release it * @hard_iface: the hard interface to free */ -static inline void -batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) +static inline void batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) { - if (atomic_dec_and_test(&hard_iface->refcount)) - batadv_hardif_release(hard_iface); + kref_put(&hard_iface->refcount, batadv_hardif_release); }
static inline struct batadv_hard_iface * @@ -85,7 +83,7 @@ batadv_primary_if_get_selected(struct batadv_priv *bat_priv) if (!hard_iface) goto out;
- if (!atomic_inc_not_zero(&hard_iface->refcount)) + if (!kref_get_unless_zero(&hard_iface->refcount)) hard_iface = NULL;
out: diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 9e3dbd88c69e..bf27007a574a 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -367,7 +367,7 @@ batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node, goto out;
if (if_outgoing != BATADV_IF_DEFAULT && - !atomic_inc_not_zero(&if_outgoing->refcount)) { + !kref_get_unless_zero(&if_outgoing->refcount)) { kfree(orig_ifinfo); orig_ifinfo = NULL; goto out; @@ -447,7 +447,7 @@ batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, if (!neigh_ifinfo) goto out;
- if (if_outgoing && !atomic_inc_not_zero(&if_outgoing->refcount)) { + if (if_outgoing && !kref_get_unless_zero(&if_outgoing->refcount)) { kfree(neigh_ifinfo); neigh_ifinfo = NULL; goto out; @@ -524,7 +524,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface, if (hardif_neigh) goto out;
- if (!atomic_inc_not_zero(&hard_iface->refcount)) + if (!kref_get_unless_zero(&hard_iface->refcount)) goto out;
hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC); @@ -635,7 +635,7 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node, if (!neigh_node) goto out;
- if (!atomic_inc_not_zero(&hard_iface->refcount)) { + if (!kref_get_unless_zero(&hard_iface->refcount)) { kfree(neigh_node); neigh_node = NULL; goto out; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 68ca39e1713d..74cb26372ed1 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -111,7 +111,7 @@ struct batadv_hard_iface { struct net_device *net_dev; u8 num_bcasts; struct kobject *hardif_obj; - atomic_t refcount; + struct kref refcount; struct packet_type batman_adv_ptype; struct net_device *soft_iface; struct rcu_head rcu;
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/originator.c | 26 ++++++++++++++++++++------ net/batman-adv/types.h | 2 +- 2 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index bf27007a574a..8b2ef8de93e9 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -82,7 +82,7 @@ batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node, if (tmp->vid != vid) continue;
- if (!atomic_inc_not_zero(&tmp->refcount)) + if (!kref_get_unless_zero(&tmp->refcount)) continue;
vlan = tmp; @@ -123,7 +123,8 @@ batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node, if (!vlan) goto out;
- atomic_set(&vlan->refcount, 2); + kref_init(&vlan->refcount); + kref_get(&vlan->refcount); vlan->vid = vid;
hlist_add_head_rcu(&vlan->list, &orig_node->vlan_list); @@ -135,14 +136,27 @@ out: }
/** - * batadv_orig_node_vlan_free_ref - decrement the refcounter and possibly free - * the originator-vlan object + * batadv_orig_node_vlan_release - release originator-vlan object from lists + * and queue for free after rcu grace period + * @ref: kref pointer of the originator-vlan object + */ +static void batadv_orig_node_vlan_release(struct kref *ref) +{ + struct batadv_orig_node_vlan *orig_vlan; + + orig_vlan = container_of(ref, struct batadv_orig_node_vlan, refcount); + + kfree_rcu(orig_vlan, rcu); +} + +/** + * batadv_orig_node_vlan_free_ref - decrement the refcounter and possibly + * release the originator-vlan object * @orig_vlan: the originator-vlan object to release */ void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan) { - if (atomic_dec_and_test(&orig_vlan->refcount)) - kfree_rcu(orig_vlan, rcu); + kref_put(&orig_vlan->refcount, batadv_orig_node_vlan_release); }
int batadv_originator_init(struct batadv_priv *bat_priv) diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 74cb26372ed1..504f3dbdbcc1 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -197,7 +197,7 @@ struct batadv_orig_node_vlan { unsigned short vid; struct batadv_vlan_tt tt; struct hlist_node list; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/distributed-arp-table.c | 2 +- net/batman-adv/gateway_client.c | 4 ++-- net/batman-adv/multicast.c | 7 ++++--- net/batman-adv/network-coding.c | 2 +- net/batman-adv/originator.c | 14 +++++++++----- net/batman-adv/originator.h | 4 ++-- net/batman-adv/translation-table.c | 4 ++-- net/batman-adv/types.h | 2 +- 8 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 921e25255cab..e3261118130a 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -542,7 +542,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, max_orig_node)) continue;
- if (!atomic_inc_not_zero(&orig_node->refcount)) + if (!kref_get_unless_zero(&orig_node->refcount)) continue;
max = tmp_max; diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 1f3847c61db8..261866e38502 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -118,7 +118,7 @@ batadv_gw_get_selected_orig(struct batadv_priv *bat_priv) if (!orig_node) goto unlock;
- if (!atomic_inc_not_zero(&orig_node->refcount)) + if (!kref_get_unless_zero(&orig_node->refcount)) orig_node = NULL;
unlock: @@ -441,7 +441,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, if (gateway->bandwidth_down == 0) return;
- if (!atomic_inc_not_zero(&orig_node->refcount)) + if (!kref_get_unless_zero(&orig_node->refcount)) return;
gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 155565e0fecc..8caa2c72efa3 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -30,6 +30,7 @@ #include <linux/in.h> #include <linux/ip.h> #include <linux/ipv6.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> @@ -447,7 +448,7 @@ batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv) hlist_for_each_entry_rcu(tmp_orig_node, &bat_priv->mcast.want_all_ipv4_list, mcast_want_all_ipv4_node) { - if (!atomic_inc_not_zero(&tmp_orig_node->refcount)) + if (!kref_get_unless_zero(&tmp_orig_node->refcount)) continue;
orig_node = tmp_orig_node; @@ -474,7 +475,7 @@ batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv) hlist_for_each_entry_rcu(tmp_orig_node, &bat_priv->mcast.want_all_ipv6_list, mcast_want_all_ipv6_node) { - if (!atomic_inc_not_zero(&tmp_orig_node->refcount)) + if (!kref_get_unless_zero(&tmp_orig_node->refcount)) continue;
orig_node = tmp_orig_node; @@ -525,7 +526,7 @@ batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv) hlist_for_each_entry_rcu(tmp_orig_node, &bat_priv->mcast.want_all_unsnoopables_list, mcast_want_all_unsnoopables_node) { - if (!atomic_inc_not_zero(&tmp_orig_node->refcount)) + if (!kref_get_unless_zero(&tmp_orig_node->refcount)) continue;
orig_node = tmp_orig_node; diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 371fc6bbf9d6..a4eb8ee4abb1 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -858,7 +858,7 @@ static struct batadv_nc_node if (!nc_node) return NULL;
- if (!atomic_inc_not_zero(&orig_neigh_node->refcount)) + if (!kref_get_unless_zero(&orig_neigh_node->refcount)) goto free;
/* Initialize nc_node */ diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 8b2ef8de93e9..eacd0e5a0238 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -18,6 +18,7 @@ #include "originator.h" #include "main.h"
+#include <linux/atomic.h> #include <linux/errno.h> #include <linux/etherdevice.h> #include <linux/fs.h> @@ -775,14 +776,17 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu) /** * batadv_orig_node_release - release orig_node from lists and queue for * free after rcu grace period - * @orig_node: the orig node to free + * @ref: kref pointer of the orig_node */ -static void batadv_orig_node_release(struct batadv_orig_node *orig_node) +static void batadv_orig_node_release(struct kref *ref) { struct hlist_node *node_tmp; struct batadv_neigh_node *neigh_node; + struct batadv_orig_node *orig_node; struct batadv_orig_ifinfo *orig_ifinfo;
+ orig_node = container_of(ref, struct batadv_orig_node, refcount); + spin_lock_bh(&orig_node->neigh_list_lock);
/* for all neighbors towards this originator ... */ @@ -812,8 +816,7 @@ static void batadv_orig_node_release(struct batadv_orig_node *orig_node) */ void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node) { - if (atomic_dec_and_test(&orig_node->refcount)) - batadv_orig_node_release(orig_node); + kref_put(&orig_node->refcount, batadv_orig_node_release); }
void batadv_originator_free(struct batadv_priv *bat_priv) @@ -885,7 +888,8 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, batadv_nc_init_orig(orig_node);
/* extra reference for return */ - atomic_set(&orig_node->refcount, 2); + kref_init(&orig_node->refcount); + kref_get(&orig_node->refcount);
orig_node->bat_priv = bat_priv; ether_addr_copy(orig_node->orig, addr); diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 745b4e4fcdc4..99507408f4cf 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -20,10 +20,10 @@
#include "main.h"
-#include <linux/atomic.h> #include <linux/compiler.h> #include <linux/if_ether.h> #include <linux/jhash.h> +#include <linux/kref.h> #include <linux/rculist.h> #include <linux/rcupdate.h> #include <linux/stddef.h> @@ -115,7 +115,7 @@ batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data) if (!batadv_compare_eth(orig_node, data)) continue;
- if (!atomic_inc_not_zero(&orig_node->refcount)) + if (!kref_get_unless_zero(&orig_node->refcount)) continue;
orig_node_tmp = orig_node; diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 68494a10848c..96b1571213bd 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1334,7 +1334,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, goto out;
INIT_HLIST_NODE(&orig_entry->list); - atomic_inc(&orig_node->refcount); + kref_get(&orig_node->refcount); batadv_tt_global_size_inc(orig_node, tt_global->common.vid); orig_entry->orig_node = orig_node; orig_entry->ttvn = ttvn; @@ -2097,7 +2097,7 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, /* found anything? */ if (best_entry) orig_node = best_entry->orig_node; - if (orig_node && !atomic_inc_not_zero(&orig_node->refcount)) + if (orig_node && !kref_get_unless_zero(&orig_node->refcount)) orig_node = NULL; rcu_read_unlock();
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 504f3dbdbcc1..aea82a121c02 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -299,7 +299,7 @@ struct batadv_orig_node { struct batadv_priv *bat_priv; /* bcast_seqno_lock protects: bcast_bits & last_bcast_seqno */ spinlock_t bcast_seqno_lock; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; #ifdef CONFIG_BATMAN_ADV_NC struct list_head in_coding_list;
From: Sven Eckelmann sven@narfation.org
batman-adv uses a self-written reference implementation which is just based on atomic_t. This is less obvious when reading the code than kref and therefore increases the change that the reference counting will be missed.
Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Marek Lindner mareklindner@neomailbox.ch Signed-off-by: Antonio Quartulli a@unstable.cc --- net/batman-adv/translation-table.c | 64 +++++++++++++++++++++++++++++--------- net/batman-adv/types.h | 2 +- 2 files changed, 51 insertions(+), 15 deletions(-)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 96b1571213bd..11882793f0a4 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -142,7 +142,7 @@ batadv_tt_hash_find(struct batadv_hashtable *hash, const u8 *addr, if (tt->vid != vid) continue;
- if (!atomic_inc_not_zero(&tt->refcount)) + if (!kref_get_unless_zero(&tt->refcount)) continue;
tt_tmp = tt; @@ -203,25 +203,59 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr, return tt_global_entry; }
-static void -batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry) +/** + * batadv_tt_local_entry_release - release tt_local_entry from lists and queue + * for free after rcu grace period + * @ref: kref pointer of the nc_node + */ +static void batadv_tt_local_entry_release(struct kref *ref) { - if (atomic_dec_and_test(&tt_local_entry->common.refcount)) - kfree_rcu(tt_local_entry, common.rcu); + struct batadv_tt_local_entry *tt_local_entry; + + tt_local_entry = container_of(ref, struct batadv_tt_local_entry, + common.refcount); + + kfree_rcu(tt_local_entry, common.rcu); }
/** - * batadv_tt_global_entry_free_ref - decrement the refcounter for a - * tt_global_entry and possibly free it - * @tt_global_entry: the object to free + * batadv_tt_local_entry_free_ref - decrement the tt_local_entry refcounter and + * possibly release it + * @tt_local_entry: tt_local_entry to be free'd + */ +static void +batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry) +{ + kref_put(&tt_local_entry->common.refcount, + batadv_tt_local_entry_release); +} + +/** + * batadv_tt_global_entry_release - release tt_global_entry from lists and queue + * for free after rcu grace period + * @ref: kref pointer of the nc_node + */ +static void batadv_tt_global_entry_release(struct kref *ref) +{ + struct batadv_tt_global_entry *tt_global_entry; + + tt_global_entry = container_of(ref, struct batadv_tt_global_entry, + common.refcount); + + batadv_tt_global_del_orig_list(tt_global_entry); + kfree_rcu(tt_global_entry, common.rcu); +} + +/** + * batadv_tt_global_entry_free_ref - decrement the tt_global_entry refcounter + * and possibly release it + * @tt_global_entry: tt_global_entry to be free'd */ static void batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) { - if (atomic_dec_and_test(&tt_global_entry->common.refcount)) { - batadv_tt_global_del_orig_list(tt_global_entry); - kfree_rcu(tt_global_entry, common.rcu); - } + kref_put(&tt_global_entry->common.refcount, + batadv_tt_global_entry_release); }
/** @@ -633,7 +667,8 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr, tt_local->common.vid = vid; if (batadv_is_wifi_netdev(in_dev)) tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; - atomic_set(&tt_local->common.refcount, 2); + kref_init(&tt_local->common.refcount); + kref_get(&tt_local->common.refcount); tt_local->last_seen = jiffies; tt_local->common.added_at = tt_local->last_seen;
@@ -1415,7 +1450,8 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, */ if (flags & BATADV_TT_CLIENT_ROAM) tt_global_entry->roam_at = jiffies; - atomic_set(&common->refcount, 2); + kref_init(&common->refcount); + kref_get(&common->refcount); common->added_at = jiffies;
INIT_HLIST_HEAD(&tt_global_entry->orig_list); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index aea82a121c02..612de23178e6 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -972,7 +972,7 @@ struct batadv_tt_common_entry { struct hlist_node hash_entry; u16 flags; unsigned long added_at; - atomic_t refcount; + struct kref refcount; struct rcu_head rcu; };
From: Antonio Quartulli a@unstable.cc Date: Wed, 10 Feb 2016 23:57:06 +0800
this is another pull request intended for net-next.
Here you have a batch of patches by Sven Eckelmann that drops our private reference counting implementation and substitutes it with the kref objects/functions.
Then you have a patch, by Simon Wunderlich, that makes the broadcast protection window code more generic so that it can be re-used in the future by other components with different requirements.
Lastly, Sven is also introducing two lockdep asserts in functions operating on our TVLV container list, to make sure that the proper lock is always acquired by the users.
Pulled, thanks Antonio.
b.a.t.m.a.n@lists.open-mesh.org