diff options
Diffstat (limited to 'net/batman-adv/originator.c')
-rw-r--r-- | net/batman-adv/originator.c | 21 |
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 | ||
105 | void orig_node_free_ref(struct kref *refcount) | 105 | static 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 | ||
140 | void 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 | |||
140 | void originator_free(struct bat_priv *bat_priv) | 146 | void 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; |
235 | free_bcast_own_sum: | 241 | free_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 | ||