So switch to kref instead of using the self-made, atomic_t-based implementation.
Signed-off-by: Sven Eckelmann sven@narfation.org --- net/batman-adv/bat_iv_ogm.c | 21 ++++++------- net/batman-adv/distributed-arp-table.c | 2 +- net/batman-adv/fragmentation.c | 2 +- net/batman-adv/gateway_client.c | 14 ++++----- net/batman-adv/hard-interface.h | 12 -------- net/batman-adv/icmp_socket.c | 2 +- net/batman-adv/network-coding.c | 4 +-- net/batman-adv/originator.c | 54 +++++++++++++--------------------- net/batman-adv/originator.h | 2 +- net/batman-adv/routing.c | 22 +++++++------- net/batman-adv/send.c | 2 +- net/batman-adv/translation-table.c | 6 ++-- net/batman-adv/types.h | 2 +- 13 files changed, 61 insertions(+), 84 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index f128e60..7d61afb 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> @@ -1000,9 +1001,9 @@ 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); + batadv_neigh_node_put(neigh_node); neigh_node = tmp_neigh_node; continue; } @@ -1113,9 +1114,9 @@ unlock: rcu_read_unlock(); out: if (neigh_node) - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node); if (router) - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); if (neigh_ifinfo) batadv_neigh_ifinfo_put(neigh_ifinfo); if (router_ifinfo) @@ -1159,7 +1160,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; @@ -1262,7 +1263,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
out: if (neigh_node) - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node); return ret; }
@@ -1565,11 +1566,11 @@ out: if (router_ifinfo) batadv_neigh_ifinfo_put(router_ifinfo); if (router) - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); if (router_router) - batadv_neigh_node_free_ref(router_router); + batadv_neigh_node_put(router_router); if (orig_neigh_router) - batadv_neigh_node_free_ref(orig_neigh_router); + batadv_neigh_node_put(orig_neigh_router); if (hardif_neigh) batadv_hardif_neigh_put(hardif_neigh);
@@ -1865,7 +1866,7 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, batman_count++;
next: - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node); if (n_ifinfo) batadv_neigh_ifinfo_put(n_ifinfo); } diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 34d0950..fa605c3 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -674,7 +674,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, ret = true; } free_neigh: - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node); free_orig: batadv_orig_node_free_ref(cand[i].orig_node); } diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 80eddf4..87b127c 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -387,7 +387,7 @@ out: if (orig_node_dst) batadv_orig_node_free_ref(orig_node_dst); if (neigh_node) - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node); return ret; }
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 8d9933a..a5b92ef 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -234,7 +234,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) batadv_gw_node_put(gw_node);
next: - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); if (router_ifinfo) batadv_neigh_ifinfo_put(router_ifinfo); } @@ -351,7 +351,7 @@ out: if (next_gw) batadv_gw_node_put(next_gw); if (router) - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); if (router_ifinfo) batadv_neigh_ifinfo_put(router_ifinfo); } @@ -416,9 +416,9 @@ out: if (curr_gw_orig) batadv_orig_node_free_ref(curr_gw_orig); if (router_gw) - batadv_neigh_node_free_ref(router_gw); + batadv_neigh_node_put(router_gw); if (router_orig) - batadv_neigh_node_free_ref(router_orig); + batadv_neigh_node_put(router_orig); if (router_gw_tq) batadv_neigh_ifinfo_put(router_gw_tq); if (router_orig_tq) @@ -624,7 +624,7 @@ out: if (router_ifinfo) batadv_neigh_ifinfo_put(router_ifinfo); if (router) - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); return ret; }
@@ -883,8 +883,8 @@ out: if (gw_node) batadv_gw_node_put(gw_node); if (neigh_old) - batadv_neigh_node_free_ref(neigh_old); + batadv_neigh_node_put(neigh_old); if (neigh_curr) - batadv_neigh_node_free_ref(neigh_curr); + batadv_neigh_node_put(neigh_curr); return out_of_range; } diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index 5a31420..7b12ea8 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h @@ -75,18 +75,6 @@ batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); }
-/** - * batadv_hardif_free_ref_now - decrement the hard interface refcounter and - * possibly free it (without rcu callback) - * @hard_iface: the hard interface to free - */ -static inline void -batadv_hardif_free_ref_now(struct batadv_hard_iface *hard_iface) -{ - if (atomic_dec_and_test(&hard_iface->refcount)) - batadv_hardif_free_rcu(&hard_iface->rcu); -} - static inline struct batadv_hard_iface * batadv_primary_if_get_selected(struct batadv_priv *bat_priv) { diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index bcabb5e..d6574cb 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -290,7 +290,7 @@ out: if (primary_if) batadv_hardif_free_ref(primary_if); if (neigh_node) - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node); if (orig_node) batadv_orig_node_free_ref(orig_node); return len; diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 329219b..41f0c2c 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -1228,9 +1228,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, res = true; out: if (router_neigh) - batadv_neigh_node_free_ref(router_neigh); + batadv_neigh_node_put(router_neigh); if (router_coding) - batadv_neigh_node_free_ref(router_coding); + batadv_neigh_node_put(router_coding); if (router_neigh_ifinfo) batadv_neigh_ifinfo_put(router_neigh_ifinfo); if (router_coding_ifinfo) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 919f464..1f10658 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -227,10 +227,11 @@ void batadv_hardif_neigh_put(struct batadv_hardif_neigh_node *hardif_neigh) }
/** - * batadv_neigh_node_free_rcu - free the neigh_node - * @rcu: rcu pointer of the neigh_node + * batadv_neigh_node_release - release neigh_node from lists and queue for + * free after rcu grace period + * @ref: kref pointer of the neigh_node */ -static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) +static void batadv_neigh_node_release(struct kref *ref) { struct hlist_node *node_tmp; struct batadv_neigh_node *neigh_node; @@ -238,7 +239,7 @@ static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) struct batadv_neigh_ifinfo *neigh_ifinfo; struct batadv_algo_ops *bao;
- neigh_node = container_of(rcu, struct batadv_neigh_node, rcu); + 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, @@ -257,32 +258,18 @@ static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) if (bao->bat_neigh_free) bao->bat_neigh_free(neigh_node);
- batadv_hardif_free_ref_now(neigh_node->if_incoming); + batadv_hardif_free_ref(neigh_node->if_incoming);
- kfree(neigh_node); + kfree_rcu(neigh_node, rcu); }
/** - * batadv_neigh_node_free_ref_now - decrement the neighbors refcounter - * and possibly free it (without rcu callback) + * batadv_neigh_node_put - decrement the neighbors refcounter and possibly free * @neigh_node: neigh neighbor to free */ -static void -batadv_neigh_node_free_ref_now(struct batadv_neigh_node *neigh_node) +void batadv_neigh_node_put(struct batadv_neigh_node *neigh_node) { - if (atomic_dec_and_test(&neigh_node->refcount)) - batadv_neigh_node_free_rcu(&neigh_node->rcu); -} - -/** - * batadv_neigh_node_free_ref - decrement the neighbors refcounter - * and possibly free 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)) - call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu); + kref_put(&neigh_node->refcount, batadv_neigh_node_release); }
/** @@ -311,7 +298,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(); @@ -504,7 +491,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; @@ -662,7 +649,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); @@ -733,7 +721,7 @@ static void batadv_orig_ifinfo_release(struct kref *ref) /* this is the last reference to this object */ router = rcu_dereference_protected(orig_ifinfo->router, true); if (router) - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router);
kfree_rcu(orig_ifinfo, rcu); } @@ -763,7 +751,7 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu) hlist_for_each_entry_safe(neigh_node, node_tmp, &orig_node->neigh_list, list) { hlist_del_rcu(&neigh_node->list); - batadv_neigh_node_free_ref_now(neigh_node); + batadv_neigh_node_put(neigh_node); }
hlist_for_each_entry_safe(orig_ifinfo, node_tmp, @@ -1047,7 +1035,7 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, neigh_purged = true;
hlist_del_rcu(&neigh_node->list); - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node); } else { /* only necessary if not the whole neighbor is to be * deleted, but some interface has been removed. @@ -1082,11 +1070,11 @@ 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) - batadv_neigh_node_free_ref(best); + batadv_neigh_node_put(best);
best = neigh; } @@ -1132,7 +1120,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT, best_neigh_node); if (best_neigh_node) - batadv_neigh_node_free_ref(best_neigh_node); + batadv_neigh_node_put(best_neigh_node);
/* ... then for all other interfaces. */ rcu_read_lock(); @@ -1149,7 +1137,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, batadv_update_route(bat_priv, orig_node, hard_iface, best_neigh_node); if (best_neigh_node) - batadv_neigh_node_free_ref(best_neigh_node); + batadv_neigh_node_put(best_neigh_node); } rcu_read_unlock();
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index db1a65d..b0506ba 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -49,7 +49,7 @@ struct batadv_neigh_node * batadv_neigh_node_new(struct batadv_orig_node *orig_node, struct batadv_hard_iface *hard_iface, const u8 *neigh_addr); -void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); +void batadv_neigh_node_put(struct batadv_neigh_node *neigh_node); struct batadv_neigh_node * batadv_orig_router_get(struct batadv_orig_node *orig_node, const struct batadv_hard_iface *if_outgoing); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 1018148..787da48 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();
@@ -98,10 +98,10 @@ static void _batadv_update_route(struct batadv_priv *bat_priv, }
if (curr_router) - batadv_neigh_node_free_ref(curr_router); + batadv_neigh_node_put(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); @@ -111,7 +111,7 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
/* decrease refcount of previous best neighbor */ if (curr_router) - batadv_neigh_node_free_ref(curr_router); + batadv_neigh_node_put(curr_router); }
/** @@ -138,7 +138,7 @@ void batadv_update_route(struct batadv_priv *bat_priv,
out: if (router) - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); }
/** @@ -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; @@ -545,7 +545,7 @@ batadv_find_router(struct batadv_priv *bat_priv, next: /* free references */ if (cand_router) { - batadv_neigh_node_free_ref(cand_router); + batadv_neigh_node_put(cand_router); cand_router = NULL; } batadv_orig_ifinfo_put(cand); @@ -562,17 +562,17 @@ next: * 3) there is no candidate at all, return the default router */ if (next_candidate) { - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router);
/* remove references to first candidate, we don't need it. */ if (first_candidate) { - batadv_neigh_node_free_ref(first_candidate_router); + batadv_neigh_node_put(first_candidate_router); batadv_orig_ifinfo_put(first_candidate); } router = next_candidate_router; orig_node->last_bonding_candidate = next_candidate; } else if (first_candidate) { - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router);
/* refcounting has already been done in the loop above. */ router = first_candidate_router; diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index c188f46..06e21fa 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -153,7 +153,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
out: if (neigh_node) - batadv_neigh_node_free_ref(neigh_node); + batadv_neigh_node_put(neigh_node);
return ret; } diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 096804e..f25b533 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1548,20 +1548,20 @@ batadv_transtable_best_orig(struct batadv_priv *bat_priv, if (best_router && bao->bat_neigh_cmp(router, BATADV_IF_DEFAULT, best_router, BATADV_IF_DEFAULT) <= 0) { - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); continue; }
/* release the refcount for the "old" best */ if (best_router) - batadv_neigh_node_free_ref(best_router); + batadv_neigh_node_put(best_router);
best_entry = orig_entry; best_router = router; }
if (best_router) - batadv_neigh_node_free_ref(best_router); + batadv_neigh_node_put(best_router);
return best_entry; } diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index a5e4310..75e1b45 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; };