diff options
-rw-r--r-- | net/batman-adv/gateway_client.c | 6 | ||||
-rw-r--r-- | net/batman-adv/icmp_socket.c | 2 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 21 | ||||
-rw-r--r-- | net/batman-adv/originator.h | 6 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 24 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 15 | ||||
-rw-r--r-- | net/batman-adv/types.h | 3 | ||||
-rw-r--r-- | net/batman-adv/unicast.c | 6 | ||||
-rw-r--r-- | net/batman-adv/vis.c | 2 |
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 | ||
60 | out: | 62 | out: |
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 | ||
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 | ||
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 @@ | |||
27 | int originator_init(struct bat_priv *bat_priv); | 27 | int originator_init(struct bat_priv *bat_priv); |
28 | void originator_free(struct bat_priv *bat_priv); | 28 | void originator_free(struct bat_priv *bat_priv); |
29 | void purge_orig_ref(struct bat_priv *bat_priv); | 29 | void purge_orig_ref(struct bat_priv *bat_priv); |
30 | void orig_node_free_ref(struct kref *refcount); | 30 | void orig_node_free_ref(struct orig_node *orig_node); |
31 | struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); | 31 | struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); |
32 | struct neigh_node *create_neighbor(struct orig_node *orig_node, | 32 | struct 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 | ||
605 | out: | 605 | out: |
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 | ||
837 | out_neigh: | 837 | out_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); |
840 | out: | 840 | out: |
841 | kref_put(&orig_node->refcount, orig_node_free_ref); | 841 | orig_node_free_ref(orig_node); |
842 | } | 842 | } |
843 | 843 | ||
844 | int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) | 844 | int 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); |
1544 | out: | 1544 | out: |
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) | |||
589 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) | 589 | struct 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; | 605 | out: |
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); |
212 | out: | 212 | out: |
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 | ||