aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/batman-adv/gateway_client.c6
-rw-r--r--net/batman-adv/icmp_socket.c2
-rw-r--r--net/batman-adv/originator.c21
-rw-r--r--net/batman-adv/originator.h6
-rw-r--r--net/batman-adv/routing.c24
-rw-r--r--net/batman-adv/translation-table.c15
-rw-r--r--net/batman-adv/types.h3
-rw-r--r--net/batman-adv/unicast.c6
-rw-r--r--net/batman-adv/vis.c2
9 files changed, 49 insertions, 36 deletions
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 41eba8a660f5..3cc43558cf9c 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -53,9 +53,11 @@ void *gw_get_selected(struct bat_priv *bat_priv)
53 goto out; 53 goto out;
54 54
55 orig_node = curr_gateway_tmp->orig_node; 55 orig_node = curr_gateway_tmp->orig_node;
56 if (!orig_node)
57 goto out;
56 58
57 if (orig_node) 59 if (!atomic_inc_not_zero(&orig_node->refcount))
58 kref_get(&orig_node->refcount); 60 orig_node = NULL;
59 61
60out: 62out:
61 rcu_read_unlock(); 63 rcu_read_unlock();
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 139b7336adf9..a0a35b1af167 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -271,7 +271,7 @@ out:
271 if (neigh_node) 271 if (neigh_node)
272 neigh_node_free_ref(neigh_node); 272 neigh_node_free_ref(neigh_node);
273 if (orig_node) 273 if (orig_node)
274 kref_put(&orig_node->refcount, orig_node_free_ref); 274 orig_node_free_ref(orig_node);
275 return len; 275 return len;
276} 276}
277 277
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
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index b4b9a09259fd..3d7a39d4df0f 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -27,7 +27,7 @@
27int originator_init(struct bat_priv *bat_priv); 27int originator_init(struct bat_priv *bat_priv);
28void originator_free(struct bat_priv *bat_priv); 28void originator_free(struct bat_priv *bat_priv);
29void purge_orig_ref(struct bat_priv *bat_priv); 29void purge_orig_ref(struct bat_priv *bat_priv);
30void orig_node_free_ref(struct kref *refcount); 30void orig_node_free_ref(struct orig_node *orig_node);
31struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); 31struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
32struct neigh_node *create_neighbor(struct orig_node *orig_node, 32struct neigh_node *create_neighbor(struct orig_node *orig_node,
33 struct orig_node *orig_neigh_node, 33 struct orig_node *orig_neigh_node,
@@ -88,8 +88,10 @@ static inline struct orig_node *orig_hash_find(struct bat_priv *bat_priv,
88 if (!compare_eth(orig_node, data)) 88 if (!compare_eth(orig_node, data))
89 continue; 89 continue;
90 90
91 if (!atomic_inc_not_zero(&orig_node->refcount))
92 continue;
93
91 orig_node_tmp = orig_node; 94 orig_node_tmp = orig_node;
92 kref_get(&orig_node_tmp->refcount);
93 break; 95 break;
94 } 96 }
95 rcu_read_unlock(); 97 rcu_read_unlock();
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index fc4c12a049da..9863c03a2137 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -420,7 +420,7 @@ static void update_orig(struct bat_priv *bat_priv,
420 neigh_node = create_neighbor(orig_node, orig_tmp, 420 neigh_node = create_neighbor(orig_node, orig_tmp,
421 ethhdr->h_source, if_incoming); 421 ethhdr->h_source, if_incoming);
422 422
423 kref_put(&orig_tmp->refcount, orig_node_free_ref); 423 orig_node_free_ref(orig_tmp);
424 if (!neigh_node) 424 if (!neigh_node)
425 goto unlock; 425 goto unlock;
426 426
@@ -604,7 +604,7 @@ static char count_real_packets(struct ethhdr *ethhdr,
604 604
605out: 605out:
606 spin_unlock_bh(&orig_node->ogm_cnt_lock); 606 spin_unlock_bh(&orig_node->ogm_cnt_lock);
607 kref_put(&orig_node->refcount, orig_node_free_ref); 607 orig_node_free_ref(orig_node);
608 return ret; 608 return ret;
609} 609}
610 610
@@ -730,7 +730,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
730 730
731 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: " 731 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
732 "originator packet from myself (via neighbor)\n"); 732 "originator packet from myself (via neighbor)\n");
733 kref_put(&orig_neigh_node->refcount, orig_node_free_ref); 733 orig_node_free_ref(orig_neigh_node);
734 return; 734 return;
735 } 735 }
736 736
@@ -835,10 +835,10 @@ void receive_bat_packet(struct ethhdr *ethhdr,
835 0, hna_buff_len, if_incoming); 835 0, hna_buff_len, if_incoming);
836 836
837out_neigh: 837out_neigh:
838 if (!is_single_hop_neigh) 838 if ((orig_neigh_node) && (!is_single_hop_neigh))
839 kref_put(&orig_neigh_node->refcount, orig_node_free_ref); 839 orig_node_free_ref(orig_neigh_node);
840out: 840out:
841 kref_put(&orig_node->refcount, orig_node_free_ref); 841 orig_node_free_ref(orig_node);
842} 842}
843 843
844int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) 844int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
@@ -952,7 +952,7 @@ out:
952 if (neigh_node) 952 if (neigh_node)
953 neigh_node_free_ref(neigh_node); 953 neigh_node_free_ref(neigh_node);
954 if (orig_node) 954 if (orig_node)
955 kref_put(&orig_node->refcount, orig_node_free_ref); 955 orig_node_free_ref(orig_node);
956 return ret; 956 return ret;
957} 957}
958 958
@@ -1028,7 +1028,7 @@ out:
1028 if (neigh_node) 1028 if (neigh_node)
1029 neigh_node_free_ref(neigh_node); 1029 neigh_node_free_ref(neigh_node);
1030 if (orig_node) 1030 if (orig_node)
1031 kref_put(&orig_node->refcount, orig_node_free_ref); 1031 orig_node_free_ref(orig_node);
1032 return ret; 1032 return ret;
1033} 1033}
1034 1034
@@ -1134,7 +1134,7 @@ out:
1134 if (neigh_node) 1134 if (neigh_node)
1135 neigh_node_free_ref(neigh_node); 1135 neigh_node_free_ref(neigh_node);
1136 if (orig_node) 1136 if (orig_node)
1137 kref_put(&orig_node->refcount, orig_node_free_ref); 1137 orig_node_free_ref(orig_node);
1138 return ret; 1138 return ret;
1139} 1139}
1140 1140
@@ -1189,7 +1189,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1189 if (!primary_orig_node) 1189 if (!primary_orig_node)
1190 goto return_router; 1190 goto return_router;
1191 1191
1192 kref_put(&primary_orig_node->refcount, orig_node_free_ref); 1192 orig_node_free_ref(primary_orig_node);
1193 } 1193 }
1194 1194
1195 /* with less than 2 candidates, we can't do any 1195 /* with less than 2 candidates, we can't do any
@@ -1401,7 +1401,7 @@ out:
1401 if (neigh_node) 1401 if (neigh_node)
1402 neigh_node_free_ref(neigh_node); 1402 neigh_node_free_ref(neigh_node);
1403 if (orig_node) 1403 if (orig_node)
1404 kref_put(&orig_node->refcount, orig_node_free_ref); 1404 orig_node_free_ref(orig_node);
1405 return ret; 1405 return ret;
1406} 1406}
1407 1407
@@ -1543,7 +1543,7 @@ spin_unlock:
1543 spin_unlock_bh(&bat_priv->orig_hash_lock); 1543 spin_unlock_bh(&bat_priv->orig_hash_lock);
1544out: 1544out:
1545 if (orig_node) 1545 if (orig_node)
1546 kref_put(&orig_node->refcount, orig_node_free_ref); 1546 orig_node_free_ref(orig_node);
1547 return ret; 1547 return ret;
1548} 1548}
1549 1549
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index cd8a58396d26..8d15b48d1692 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -589,17 +589,20 @@ void hna_global_free(struct bat_priv *bat_priv)
589struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) 589struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
590{ 590{
591 struct hna_global_entry *hna_global_entry; 591 struct hna_global_entry *hna_global_entry;
592 struct orig_node *orig_node = NULL;
592 593
593 spin_lock_bh(&bat_priv->hna_ghash_lock); 594 spin_lock_bh(&bat_priv->hna_ghash_lock);
594 hna_global_entry = hna_global_hash_find(bat_priv, addr); 595 hna_global_entry = hna_global_hash_find(bat_priv, addr);
595 596
596 if (hna_global_entry) 597 if (!hna_global_entry)
597 kref_get(&hna_global_entry->orig_node->refcount); 598 goto out;
598 599
599 spin_unlock_bh(&bat_priv->hna_ghash_lock); 600 if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount))
601 goto out;
600 602
601 if (!hna_global_entry) 603 orig_node = hna_global_entry->orig_node;
602 return NULL;
603 604
604 return hna_global_entry->orig_node; 605out:
606 spin_unlock_bh(&bat_priv->hna_ghash_lock);
607 return orig_node;
605} 608}
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 40365b81bc40..1be76feddee1 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -84,7 +84,8 @@ struct orig_node {
84 struct hlist_head neigh_list; 84 struct hlist_head neigh_list;
85 struct list_head frag_list; 85 struct list_head frag_list;
86 spinlock_t neigh_list_lock; /* protects neighbor list */ 86 spinlock_t neigh_list_lock; /* protects neighbor list */
87 struct kref refcount; 87 atomic_t refcount;
88 struct rcu_head rcu;
88 struct hlist_node hash_entry; 89 struct hlist_node hash_entry;
89 struct bat_priv *bat_priv; 90 struct bat_priv *bat_priv;
90 unsigned long last_frag_packet; 91 unsigned long last_frag_packet;
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 2d5daac52034..2ab819841231 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -211,7 +211,7 @@ unlock:
211 spin_unlock_bh(&bat_priv->orig_hash_lock); 211 spin_unlock_bh(&bat_priv->orig_hash_lock);
212out: 212out:
213 if (orig_node) 213 if (orig_node)
214 kref_put(&orig_node->refcount, orig_node_free_ref); 214 orig_node_free_ref(orig_node);
215 return ret; 215 return ret;
216} 216}
217 217
@@ -280,7 +280,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
280{ 280{
281 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 281 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
282 struct unicast_packet *unicast_packet; 282 struct unicast_packet *unicast_packet;
283 struct orig_node *orig_node = NULL; 283 struct orig_node *orig_node;
284 struct batman_if *batman_if; 284 struct batman_if *batman_if;
285 struct neigh_node *neigh_node; 285 struct neigh_node *neigh_node;
286 int data_len = skb->len; 286 int data_len = skb->len;
@@ -347,7 +347,7 @@ out:
347 if (neigh_node) 347 if (neigh_node)
348 neigh_node_free_ref(neigh_node); 348 neigh_node_free_ref(neigh_node);
349 if (orig_node) 349 if (orig_node)
350 kref_put(&orig_node->refcount, orig_node_free_ref); 350 orig_node_free_ref(orig_node);
351 if (ret == 1) 351 if (ret == 1)
352 kfree_skb(skb); 352 kfree_skb(skb);
353 return ret; 353 return ret;
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index d179acabb04c..89722425dcb2 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -826,7 +826,7 @@ out:
826 if (neigh_node) 826 if (neigh_node)
827 neigh_node_free_ref(neigh_node); 827 neigh_node_free_ref(neigh_node);
828 if (orig_node) 828 if (orig_node)
829 kref_put(&orig_node->refcount, orig_node_free_ref); 829 orig_node_free_ref(orig_node);
830 return; 830 return;
831} 831}
832 832