aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/originator.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/originator.c')
-rw-r--r--net/batman-adv/originator.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index bdcb399329dd..a70debebfc5b 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -102,13 +102,13 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
102 return neigh_node; 102 return neigh_node;
103} 103}
104 104
105void orig_node_free_ref(struct kref *refcount) 105static void orig_node_free_rcu(struct rcu_head *rcu)
106{ 106{
107 struct hlist_node *node, *node_tmp; 107 struct hlist_node *node, *node_tmp;
108 struct neigh_node *neigh_node, *tmp_neigh_node; 108 struct neigh_node *neigh_node, *tmp_neigh_node;
109 struct orig_node *orig_node; 109 struct orig_node *orig_node;
110 110
111 orig_node = container_of(refcount, struct orig_node, refcount); 111 orig_node = container_of(rcu, struct orig_node, rcu);
112 112
113 spin_lock_bh(&orig_node->neigh_list_lock); 113 spin_lock_bh(&orig_node->neigh_list_lock);
114 114
@@ -137,6 +137,12 @@ void orig_node_free_ref(struct kref *refcount)
137 kfree(orig_node); 137 kfree(orig_node);
138} 138}
139 139
140void orig_node_free_ref(struct orig_node *orig_node)
141{
142 if (atomic_dec_and_test(&orig_node->refcount))
143 call_rcu(&orig_node->rcu, orig_node_free_rcu);
144}
145
140void originator_free(struct bat_priv *bat_priv) 146void originator_free(struct bat_priv *bat_priv)
141{ 147{
142 struct hashtable_t *hash = bat_priv->orig_hash; 148 struct hashtable_t *hash = bat_priv->orig_hash;
@@ -163,7 +169,7 @@ void originator_free(struct bat_priv *bat_priv)
163 head, hash_entry) { 169 head, hash_entry) {
164 170
165 hlist_del_rcu(node); 171 hlist_del_rcu(node);
166 kref_put(&orig_node->refcount, orig_node_free_ref); 172 orig_node_free_ref(orig_node);
167 } 173 }
168 spin_unlock_bh(list_lock); 174 spin_unlock_bh(list_lock);
169 } 175 }
@@ -196,7 +202,9 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
196 spin_lock_init(&orig_node->ogm_cnt_lock); 202 spin_lock_init(&orig_node->ogm_cnt_lock);
197 spin_lock_init(&orig_node->bcast_seqno_lock); 203 spin_lock_init(&orig_node->bcast_seqno_lock);
198 spin_lock_init(&orig_node->neigh_list_lock); 204 spin_lock_init(&orig_node->neigh_list_lock);
199 kref_init(&orig_node->refcount); 205
206 /* extra reference for return */
207 atomic_set(&orig_node->refcount, 2);
200 208
201 orig_node->bat_priv = bat_priv; 209 orig_node->bat_priv = bat_priv;
202 memcpy(orig_node->orig, addr, ETH_ALEN); 210 memcpy(orig_node->orig, addr, ETH_ALEN);
@@ -229,8 +237,6 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
229 if (hash_added < 0) 237 if (hash_added < 0)
230 goto free_bcast_own_sum; 238 goto free_bcast_own_sum;
231 239
232 /* extra reference for return */
233 kref_get(&orig_node->refcount);
234 return orig_node; 240 return orig_node;
235free_bcast_own_sum: 241free_bcast_own_sum:
236 kfree(orig_node->bcast_own_sum); 242 kfree(orig_node->bcast_own_sum);
@@ -348,8 +354,7 @@ static void _purge_orig(struct bat_priv *bat_priv)
348 if (orig_node->gw_flags) 354 if (orig_node->gw_flags)
349 gw_node_delete(bat_priv, orig_node); 355 gw_node_delete(bat_priv, orig_node);
350 hlist_del_rcu(node); 356 hlist_del_rcu(node);
351 kref_put(&orig_node->refcount, 357 orig_node_free_ref(orig_node);
352 orig_node_free_ref);
353 continue; 358 continue;
354 } 359 }
355 360