aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2011-02-18 07:28:09 -0500
committerMarek Lindner <lindner_marek@yahoo.de>2011-03-05 06:52:00 -0500
commit7aadf889e897155c45cda230d2a6701ad1fbff61 (patch)
tree4a31df411c29844afe25ccde17d2ff9e618241c1 /net/batman-adv
parent39901e716275da4e831b40f9e45a1b61d6a776dc (diff)
batman-adv: remove extra layer between hash and hash element - hash bucket
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/hash.c8
-rw-r--r--net/batman-adv/hash.h95
-rw-r--r--net/batman-adv/icmp_socket.c5
-rw-r--r--net/batman-adv/originator.c73
-rw-r--r--net/batman-adv/originator.h35
-rw-r--r--net/batman-adv/routing.c40
-rw-r--r--net/batman-adv/translation-table.c208
-rw-r--r--net/batman-adv/types.h4
-rw-r--r--net/batman-adv/unicast.c21
-rw-r--r--net/batman-adv/vis.c103
10 files changed, 298 insertions, 294 deletions
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c
index 02653666a26..c5213d8f2cc 100644
--- a/net/batman-adv/hash.c
+++ b/net/batman-adv/hash.c
@@ -68,11 +68,3 @@ free_hash:
68 kfree(hash); 68 kfree(hash);
69 return NULL; 69 return NULL;
70} 70}
71
72void bucket_free_rcu(struct rcu_head *rcu)
73{
74 struct element_t *bucket;
75
76 bucket = container_of(rcu, struct element_t, rcu);
77 kfree(bucket);
78}
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index 3c48c6bb1ac..434822b2747 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -28,19 +28,13 @@
28 * compare 2 element datas for their keys, 28 * compare 2 element datas for their keys,
29 * return 0 if same and not 0 if not 29 * return 0 if same and not 0 if not
30 * same */ 30 * same */
31typedef int (*hashdata_compare_cb)(void *, void *); 31typedef int (*hashdata_compare_cb)(struct hlist_node *, void *);
32 32
33/* the hashfunction, should return an index 33/* the hashfunction, should return an index
34 * based on the key in the data of the first 34 * based on the key in the data of the first
35 * argument and the size the second */ 35 * argument and the size the second */
36typedef int (*hashdata_choose_cb)(void *, int); 36typedef int (*hashdata_choose_cb)(void *, int);
37typedef void (*hashdata_free_cb)(void *, void *); 37typedef void (*hashdata_free_cb)(struct hlist_node *, void *);
38
39struct element_t {
40 void *data; /* pointer to the data */
41 struct hlist_node hlist; /* bucket list pointer */
42 struct rcu_head rcu;
43};
44 38
45struct hashtable_t { 39struct hashtable_t {
46 struct hlist_head *table; /* the hashtable itself with the buckets */ 40 struct hlist_head *table; /* the hashtable itself with the buckets */
@@ -54,8 +48,6 @@ struct hashtable_t *hash_new(int size);
54/* free only the hashtable and the hash itself. */ 48/* free only the hashtable and the hash itself. */
55void hash_destroy(struct hashtable_t *hash); 49void hash_destroy(struct hashtable_t *hash);
56 50
57void bucket_free_rcu(struct rcu_head *rcu);
58
59/* remove the hash structure. if hashdata_free_cb != NULL, this function will be 51/* remove the hash structure. if hashdata_free_cb != NULL, this function will be
60 * called to remove the elements inside of the hash. if you don't remove the 52 * called to remove the elements inside of the hash. if you don't remove the
61 * elements, memory might be leaked. */ 53 * elements, memory might be leaked. */
@@ -63,8 +55,7 @@ static inline void hash_delete(struct hashtable_t *hash,
63 hashdata_free_cb free_cb, void *arg) 55 hashdata_free_cb free_cb, void *arg)
64{ 56{
65 struct hlist_head *head; 57 struct hlist_head *head;
66 struct hlist_node *walk, *safe; 58 struct hlist_node *node, *node_tmp;
67 struct element_t *bucket;
68 spinlock_t *list_lock; /* spinlock to protect write access */ 59 spinlock_t *list_lock; /* spinlock to protect write access */
69 int i; 60 int i;
70 61
@@ -73,12 +64,11 @@ static inline void hash_delete(struct hashtable_t *hash,
73 list_lock = &hash->list_locks[i]; 64 list_lock = &hash->list_locks[i];
74 65
75 spin_lock_bh(list_lock); 66 spin_lock_bh(list_lock);
76 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 67 hlist_for_each_safe(node, node_tmp, head) {
77 if (free_cb) 68 hlist_del_rcu(node);
78 free_cb(bucket->data, arg);
79 69
80 hlist_del_rcu(walk); 70 if (free_cb)
81 call_rcu(&bucket->rcu, bucket_free_rcu); 71 free_cb(node, arg);
82 } 72 }
83 spin_unlock_bh(list_lock); 73 spin_unlock_bh(list_lock);
84 } 74 }
@@ -89,12 +79,12 @@ static inline void hash_delete(struct hashtable_t *hash,
89/* adds data to the hashtable. returns 0 on success, -1 on error */ 79/* adds data to the hashtable. returns 0 on success, -1 on error */
90static inline int hash_add(struct hashtable_t *hash, 80static inline int hash_add(struct hashtable_t *hash,
91 hashdata_compare_cb compare, 81 hashdata_compare_cb compare,
92 hashdata_choose_cb choose, void *data) 82 hashdata_choose_cb choose,
83 void *data, struct hlist_node *data_node)
93{ 84{
94 int index; 85 int index;
95 struct hlist_head *head; 86 struct hlist_head *head;
96 struct hlist_node *walk, *safe; 87 struct hlist_node *node;
97 struct element_t *bucket;
98 spinlock_t *list_lock; /* spinlock to protect write access */ 88 spinlock_t *list_lock; /* spinlock to protect write access */
99 89
100 if (!hash) 90 if (!hash)
@@ -105,21 +95,17 @@ static inline int hash_add(struct hashtable_t *hash,
105 list_lock = &hash->list_locks[index]; 95 list_lock = &hash->list_locks[index];
106 96
107 rcu_read_lock(); 97 rcu_read_lock();
108 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 98 __hlist_for_each_rcu(node, head) {
109 if (compare(bucket->data, data)) 99 if (!compare(node, data))
110 goto err_unlock; 100 continue;
101
102 goto err_unlock;
111 } 103 }
112 rcu_read_unlock(); 104 rcu_read_unlock();
113 105
114 /* no duplicate found in list, add new element */ 106 /* no duplicate found in list, add new element */
115 bucket = kmalloc(sizeof(struct element_t), GFP_ATOMIC);
116 if (!bucket)
117 goto err;
118
119 bucket->data = data;
120
121 spin_lock_bh(list_lock); 107 spin_lock_bh(list_lock);
122 hlist_add_head_rcu(&bucket->hlist, head); 108 hlist_add_head_rcu(data_node, head);
123 spin_unlock_bh(list_lock); 109 spin_unlock_bh(list_lock);
124 110
125 return 0; 111 return 0;
@@ -139,8 +125,7 @@ static inline void *hash_remove(struct hashtable_t *hash,
139 hashdata_choose_cb choose, void *data) 125 hashdata_choose_cb choose, void *data)
140{ 126{
141 size_t index; 127 size_t index;
142 struct hlist_node *walk; 128 struct hlist_node *node;
143 struct element_t *bucket;
144 struct hlist_head *head; 129 struct hlist_head *head;
145 void *data_save = NULL; 130 void *data_save = NULL;
146 131
@@ -148,49 +133,17 @@ static inline void *hash_remove(struct hashtable_t *hash,
148 head = &hash->table[index]; 133 head = &hash->table[index];
149 134
150 spin_lock_bh(&hash->list_locks[index]); 135 spin_lock_bh(&hash->list_locks[index]);
151 hlist_for_each_entry(bucket, walk, head, hlist) { 136 hlist_for_each(node, head) {
152 if (compare(bucket->data, data)) { 137 if (!compare(node, data))
153 data_save = bucket->data; 138 continue;
154 hlist_del_rcu(walk); 139
155 call_rcu(&bucket->rcu, bucket_free_rcu); 140 data_save = node;
156 break; 141 hlist_del_rcu(node);
157 } 142 break;
158 } 143 }
159 spin_unlock_bh(&hash->list_locks[index]); 144 spin_unlock_bh(&hash->list_locks[index]);
160 145
161 return data_save; 146 return data_save;
162} 147}
163 148
164/**
165 * finds data, based on the key in keydata. returns the found data on success,
166 * or NULL on error
167 *
168 * caller must lock with rcu_read_lock() / rcu_read_unlock()
169 **/
170static inline void *hash_find(struct hashtable_t *hash,
171 hashdata_compare_cb compare,
172 hashdata_choose_cb choose, void *keydata)
173{
174 int index;
175 struct hlist_head *head;
176 struct hlist_node *walk;
177 struct element_t *bucket;
178 void *bucket_data = NULL;
179
180 if (!hash)
181 return NULL;
182
183 index = choose(keydata , hash->size);
184 head = &hash->table[index];
185
186 hlist_for_each_entry(bucket, walk, head, hlist) {
187 if (compare(bucket->data, keydata)) {
188 bucket_data = bucket->data;
189 break;
190 }
191 }
192
193 return bucket_data;
194}
195
196#endif /* _NET_BATMAN_ADV_HASH_H_ */ 149#endif /* _NET_BATMAN_ADV_HASH_H_ */
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 7fa5bb8a940..139b7336adf 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -222,14 +222,11 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
222 222
223 spin_lock_bh(&bat_priv->orig_hash_lock); 223 spin_lock_bh(&bat_priv->orig_hash_lock);
224 rcu_read_lock(); 224 rcu_read_lock();
225 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 225 orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
226 compare_orig, choose_orig,
227 icmp_packet->dst));
228 226
229 if (!orig_node) 227 if (!orig_node)
230 goto unlock; 228 goto unlock;
231 229
232 kref_get(&orig_node->refcount);
233 neigh_node = orig_node->router; 230 neigh_node = orig_node->router;
234 231
235 if (!neigh_node) 232 if (!neigh_node)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index d9a8e316c24..bdcb399329d 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -140,9 +140,8 @@ void orig_node_free_ref(struct kref *refcount)
140void originator_free(struct bat_priv *bat_priv) 140void originator_free(struct bat_priv *bat_priv)
141{ 141{
142 struct hashtable_t *hash = bat_priv->orig_hash; 142 struct hashtable_t *hash = bat_priv->orig_hash;
143 struct hlist_node *walk, *safe; 143 struct hlist_node *node, *node_tmp;
144 struct hlist_head *head; 144 struct hlist_head *head;
145 struct element_t *bucket;
146 spinlock_t *list_lock; /* spinlock to protect write access */ 145 spinlock_t *list_lock; /* spinlock to protect write access */
147 struct orig_node *orig_node; 146 struct orig_node *orig_node;
148 int i; 147 int i;
@@ -160,11 +159,10 @@ void originator_free(struct bat_priv *bat_priv)
160 list_lock = &hash->list_locks[i]; 159 list_lock = &hash->list_locks[i];
161 160
162 spin_lock_bh(list_lock); 161 spin_lock_bh(list_lock);
163 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 162 hlist_for_each_entry_safe(orig_node, node, node_tmp,
164 orig_node = bucket->data; 163 head, hash_entry) {
165 164
166 hlist_del_rcu(walk); 165 hlist_del_rcu(node);
167 call_rcu(&bucket->rcu, bucket_free_rcu);
168 kref_put(&orig_node->refcount, orig_node_free_ref); 166 kref_put(&orig_node->refcount, orig_node_free_ref);
169 } 167 }
170 spin_unlock_bh(list_lock); 168 spin_unlock_bh(list_lock);
@@ -174,18 +172,6 @@ void originator_free(struct bat_priv *bat_priv)
174 spin_unlock_bh(&bat_priv->orig_hash_lock); 172 spin_unlock_bh(&bat_priv->orig_hash_lock);
175} 173}
176 174
177static void bucket_free_orig_rcu(struct rcu_head *rcu)
178{
179 struct element_t *bucket;
180 struct orig_node *orig_node;
181
182 bucket = container_of(rcu, struct element_t, rcu);
183 orig_node = bucket->data;
184
185 kref_put(&orig_node->refcount, orig_node_free_ref);
186 kfree(bucket);
187}
188
189/* this function finds or creates an originator entry for the given 175/* this function finds or creates an originator entry for the given
190 * address if it does not exits */ 176 * address if it does not exits */
191struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) 177struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
@@ -194,16 +180,9 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
194 int size; 180 int size;
195 int hash_added; 181 int hash_added;
196 182
197 rcu_read_lock(); 183 orig_node = orig_hash_find(bat_priv, addr);
198 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 184 if (orig_node)
199 compare_orig, choose_orig,
200 addr));
201 rcu_read_unlock();
202
203 if (orig_node) {
204 kref_get(&orig_node->refcount);
205 return orig_node; 185 return orig_node;
206 }
207 186
208 bat_dbg(DBG_BATMAN, bat_priv, 187 bat_dbg(DBG_BATMAN, bat_priv,
209 "Creating new originator: %pM\n", addr); 188 "Creating new originator: %pM\n", addr);
@@ -245,8 +224,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
245 if (!orig_node->bcast_own_sum) 224 if (!orig_node->bcast_own_sum)
246 goto free_bcast_own; 225 goto free_bcast_own;
247 226
248 hash_added = hash_add(bat_priv->orig_hash, compare_orig, choose_orig, 227 hash_added = hash_add(bat_priv->orig_hash, compare_orig,
249 orig_node); 228 choose_orig, orig_node, &orig_node->hash_entry);
250 if (hash_added < 0) 229 if (hash_added < 0)
251 goto free_bcast_own_sum; 230 goto free_bcast_own_sum;
252 231
@@ -346,9 +325,8 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
346static void _purge_orig(struct bat_priv *bat_priv) 325static void _purge_orig(struct bat_priv *bat_priv)
347{ 326{
348 struct hashtable_t *hash = bat_priv->orig_hash; 327 struct hashtable_t *hash = bat_priv->orig_hash;
349 struct hlist_node *walk, *safe; 328 struct hlist_node *node, *node_tmp;
350 struct hlist_head *head; 329 struct hlist_head *head;
351 struct element_t *bucket;
352 spinlock_t *list_lock; /* spinlock to protect write access */ 330 spinlock_t *list_lock; /* spinlock to protect write access */
353 struct orig_node *orig_node; 331 struct orig_node *orig_node;
354 int i; 332 int i;
@@ -364,14 +342,14 @@ static void _purge_orig(struct bat_priv *bat_priv)
364 list_lock = &hash->list_locks[i]; 342 list_lock = &hash->list_locks[i];
365 343
366 spin_lock_bh(list_lock); 344 spin_lock_bh(list_lock);
367 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 345 hlist_for_each_entry_safe(orig_node, node, node_tmp,
368 orig_node = bucket->data; 346 head, hash_entry) {
369
370 if (purge_orig_node(bat_priv, orig_node)) { 347 if (purge_orig_node(bat_priv, orig_node)) {
371 if (orig_node->gw_flags) 348 if (orig_node->gw_flags)
372 gw_node_delete(bat_priv, orig_node); 349 gw_node_delete(bat_priv, orig_node);
373 hlist_del_rcu(walk); 350 hlist_del_rcu(node);
374 call_rcu(&bucket->rcu, bucket_free_orig_rcu); 351 kref_put(&orig_node->refcount,
352 orig_node_free_ref);
375 continue; 353 continue;
376 } 354 }
377 355
@@ -411,9 +389,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
411 struct net_device *net_dev = (struct net_device *)seq->private; 389 struct net_device *net_dev = (struct net_device *)seq->private;
412 struct bat_priv *bat_priv = netdev_priv(net_dev); 390 struct bat_priv *bat_priv = netdev_priv(net_dev);
413 struct hashtable_t *hash = bat_priv->orig_hash; 391 struct hashtable_t *hash = bat_priv->orig_hash;
414 struct hlist_node *walk, *node; 392 struct hlist_node *node, *node_tmp;
415 struct hlist_head *head; 393 struct hlist_head *head;
416 struct element_t *bucket;
417 struct orig_node *orig_node; 394 struct orig_node *orig_node;
418 struct neigh_node *neigh_node; 395 struct neigh_node *neigh_node;
419 int batman_count = 0; 396 int batman_count = 0;
@@ -447,9 +424,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
447 head = &hash->table[i]; 424 head = &hash->table[i];
448 425
449 rcu_read_lock(); 426 rcu_read_lock();
450 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 427 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
451 orig_node = bucket->data;
452
453 if (!orig_node->router) 428 if (!orig_node->router)
454 continue; 429 continue;
455 430
@@ -468,7 +443,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
468 neigh_node->addr, 443 neigh_node->addr,
469 neigh_node->if_incoming->net_dev->name); 444 neigh_node->if_incoming->net_dev->name);
470 445
471 hlist_for_each_entry_rcu(neigh_node, node, 446 hlist_for_each_entry_rcu(neigh_node, node_tmp,
472 &orig_node->neigh_list, list) { 447 &orig_node->neigh_list, list) {
473 seq_printf(seq, " %pM (%3i)", neigh_node->addr, 448 seq_printf(seq, " %pM (%3i)", neigh_node->addr,
474 neigh_node->tq_avg); 449 neigh_node->tq_avg);
@@ -522,9 +497,8 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
522{ 497{
523 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); 498 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
524 struct hashtable_t *hash = bat_priv->orig_hash; 499 struct hashtable_t *hash = bat_priv->orig_hash;
525 struct hlist_node *walk; 500 struct hlist_node *node;
526 struct hlist_head *head; 501 struct hlist_head *head;
527 struct element_t *bucket;
528 struct orig_node *orig_node; 502 struct orig_node *orig_node;
529 int i, ret; 503 int i, ret;
530 504
@@ -536,9 +510,7 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
536 head = &hash->table[i]; 510 head = &hash->table[i];
537 511
538 rcu_read_lock(); 512 rcu_read_lock();
539 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 513 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
540 orig_node = bucket->data;
541
542 spin_lock_bh(&orig_node->ogm_cnt_lock); 514 spin_lock_bh(&orig_node->ogm_cnt_lock);
543 ret = orig_node_add_if(orig_node, max_if_num); 515 ret = orig_node_add_if(orig_node, max_if_num);
544 spin_unlock_bh(&orig_node->ogm_cnt_lock); 516 spin_unlock_bh(&orig_node->ogm_cnt_lock);
@@ -614,9 +586,8 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
614{ 586{
615 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); 587 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
616 struct hashtable_t *hash = bat_priv->orig_hash; 588 struct hashtable_t *hash = bat_priv->orig_hash;
617 struct hlist_node *walk; 589 struct hlist_node *node;
618 struct hlist_head *head; 590 struct hlist_head *head;
619 struct element_t *bucket;
620 struct batman_if *batman_if_tmp; 591 struct batman_if *batman_if_tmp;
621 struct orig_node *orig_node; 592 struct orig_node *orig_node;
622 int i, ret; 593 int i, ret;
@@ -629,9 +600,7 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
629 head = &hash->table[i]; 600 head = &hash->table[i];
630 601
631 rcu_read_lock(); 602 rcu_read_lock();
632 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 603 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
633 orig_node = bucket->data;
634
635 spin_lock_bh(&orig_node->ogm_cnt_lock); 604 spin_lock_bh(&orig_node->ogm_cnt_lock);
636 ret = orig_node_del_if(orig_node, max_if_num, 605 ret = orig_node_del_if(orig_node, max_if_num,
637 batman_if->if_num); 606 batman_if->if_num);
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 84d96e2eea4..b4b9a09259f 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -22,6 +22,8 @@
22#ifndef _NET_BATMAN_ADV_ORIGINATOR_H_ 22#ifndef _NET_BATMAN_ADV_ORIGINATOR_H_
23#define _NET_BATMAN_ADV_ORIGINATOR_H_ 23#define _NET_BATMAN_ADV_ORIGINATOR_H_
24 24
25#include "hash.h"
26
25int originator_init(struct bat_priv *bat_priv); 27int originator_init(struct bat_priv *bat_priv);
26void originator_free(struct bat_priv *bat_priv); 28void originator_free(struct bat_priv *bat_priv);
27void purge_orig_ref(struct bat_priv *bat_priv); 29void purge_orig_ref(struct bat_priv *bat_priv);
@@ -38,8 +40,10 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
38 40
39 41
40/* returns 1 if they are the same originator */ 42/* returns 1 if they are the same originator */
41static inline int compare_orig(void *data1, void *data2) 43static inline int compare_orig(struct hlist_node *node, void *data2)
42{ 44{
45 void *data1 = container_of(node, struct orig_node, hash_entry);
46
43 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); 47 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
44} 48}
45 49
@@ -64,4 +68,33 @@ static inline int choose_orig(void *data, int32_t size)
64 return hash % size; 68 return hash % size;
65} 69}
66 70
71static inline struct orig_node *orig_hash_find(struct bat_priv *bat_priv,
72 void *data)
73{
74 struct hashtable_t *hash = bat_priv->orig_hash;
75 struct hlist_head *head;
76 struct hlist_node *node;
77 struct orig_node *orig_node, *orig_node_tmp = NULL;
78 int index;
79
80 if (!hash)
81 return NULL;
82
83 index = choose_orig(data, hash->size);
84 head = &hash->table[index];
85
86 rcu_read_lock();
87 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
88 if (!compare_eth(orig_node, data))
89 continue;
90
91 orig_node_tmp = orig_node;
92 kref_get(&orig_node_tmp->refcount);
93 break;
94 }
95 rcu_read_unlock();
96
97 return orig_node_tmp;
98}
99
67#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */ 100#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index b54bf6ec637..fc4c12a049d 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -39,9 +39,8 @@ void slide_own_bcast_window(struct batman_if *batman_if)
39{ 39{
40 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); 40 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
41 struct hashtable_t *hash = bat_priv->orig_hash; 41 struct hashtable_t *hash = bat_priv->orig_hash;
42 struct hlist_node *walk; 42 struct hlist_node *node;
43 struct hlist_head *head; 43 struct hlist_head *head;
44 struct element_t *bucket;
45 struct orig_node *orig_node; 44 struct orig_node *orig_node;
46 unsigned long *word; 45 unsigned long *word;
47 int i; 46 int i;
@@ -53,8 +52,7 @@ void slide_own_bcast_window(struct batman_if *batman_if)
53 head = &hash->table[i]; 52 head = &hash->table[i];
54 53
55 rcu_read_lock(); 54 rcu_read_lock();
56 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 55 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
57 orig_node = bucket->data;
58 spin_lock_bh(&orig_node->ogm_cnt_lock); 56 spin_lock_bh(&orig_node->ogm_cnt_lock);
59 word_index = batman_if->if_num * NUM_WORDS; 57 word_index = batman_if->if_num * NUM_WORDS;
60 word = &(orig_node->bcast_own[word_index]); 58 word = &(orig_node->bcast_own[word_index]);
@@ -908,14 +906,11 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
908 /* get routing information */ 906 /* get routing information */
909 spin_lock_bh(&bat_priv->orig_hash_lock); 907 spin_lock_bh(&bat_priv->orig_hash_lock);
910 rcu_read_lock(); 908 rcu_read_lock();
911 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 909 orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
912 compare_orig, choose_orig,
913 icmp_packet->orig));
914 910
915 if (!orig_node) 911 if (!orig_node)
916 goto unlock; 912 goto unlock;
917 913
918 kref_get(&orig_node->refcount);
919 neigh_node = orig_node->router; 914 neigh_node = orig_node->router;
920 915
921 if (!neigh_node) 916 if (!neigh_node)
@@ -987,14 +982,11 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
987 /* get routing information */ 982 /* get routing information */
988 spin_lock_bh(&bat_priv->orig_hash_lock); 983 spin_lock_bh(&bat_priv->orig_hash_lock);
989 rcu_read_lock(); 984 rcu_read_lock();
990 orig_node = ((struct orig_node *) 985 orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
991 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
992 icmp_packet->orig));
993 986
994 if (!orig_node) 987 if (!orig_node)
995 goto unlock; 988 goto unlock;
996 989
997 kref_get(&orig_node->refcount);
998 neigh_node = orig_node->router; 990 neigh_node = orig_node->router;
999 991
1000 if (!neigh_node) 992 if (!neigh_node)
@@ -1098,13 +1090,11 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
1098 /* get routing information */ 1090 /* get routing information */
1099 spin_lock_bh(&bat_priv->orig_hash_lock); 1091 spin_lock_bh(&bat_priv->orig_hash_lock);
1100 rcu_read_lock(); 1092 rcu_read_lock();
1101 orig_node = ((struct orig_node *) 1093 orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
1102 hash_find(bat_priv->orig_hash, compare_orig, choose_orig, 1094
1103 icmp_packet->dst));
1104 if (!orig_node) 1095 if (!orig_node)
1105 goto unlock; 1096 goto unlock;
1106 1097
1107 kref_get(&orig_node->refcount);
1108 neigh_node = orig_node->router; 1098 neigh_node = orig_node->router;
1109 1099
1110 if (!neigh_node) 1100 if (!neigh_node)
@@ -1194,11 +1184,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1194 if (compare_eth(router_orig->primary_addr, router_orig->orig)) { 1184 if (compare_eth(router_orig->primary_addr, router_orig->orig)) {
1195 primary_orig_node = router_orig; 1185 primary_orig_node = router_orig;
1196 } else { 1186 } else {
1197 primary_orig_node = hash_find(bat_priv->orig_hash, compare_orig, 1187 primary_orig_node = orig_hash_find(bat_priv,
1198 choose_orig, 1188 router_orig->primary_addr);
1199 router_orig->primary_addr);
1200 if (!primary_orig_node) 1189 if (!primary_orig_node)
1201 goto return_router; 1190 goto return_router;
1191
1192 kref_put(&primary_orig_node->refcount, orig_node_free_ref);
1202 } 1193 }
1203 1194
1204 /* with less than 2 candidates, we can't do any 1195 /* with less than 2 candidates, we can't do any
@@ -1344,13 +1335,11 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1344 /* get routing information */ 1335 /* get routing information */
1345 spin_lock_bh(&bat_priv->orig_hash_lock); 1336 spin_lock_bh(&bat_priv->orig_hash_lock);
1346 rcu_read_lock(); 1337 rcu_read_lock();
1347 orig_node = ((struct orig_node *) 1338 orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
1348 hash_find(bat_priv->orig_hash, compare_orig, choose_orig, 1339
1349 unicast_packet->dest));
1350 if (!orig_node) 1340 if (!orig_node)
1351 goto unlock; 1341 goto unlock;
1352 1342
1353 kref_get(&orig_node->refcount);
1354 rcu_read_unlock(); 1343 rcu_read_unlock();
1355 1344
1356 /* find_router() increases neigh_nodes refcount if found. */ 1345 /* find_router() increases neigh_nodes refcount if found. */
@@ -1508,14 +1497,11 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
1508 1497
1509 spin_lock_bh(&bat_priv->orig_hash_lock); 1498 spin_lock_bh(&bat_priv->orig_hash_lock);
1510 rcu_read_lock(); 1499 rcu_read_lock();
1511 orig_node = ((struct orig_node *) 1500 orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
1512 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
1513 bcast_packet->orig));
1514 1501
1515 if (!orig_node) 1502 if (!orig_node)
1516 goto rcu_unlock; 1503 goto rcu_unlock;
1517 1504
1518 kref_get(&orig_node->refcount);
1519 rcu_read_unlock(); 1505 rcu_read_unlock();
1520 1506
1521 spin_lock_bh(&orig_node->bcast_seqno_lock); 1507 spin_lock_bh(&orig_node->bcast_seqno_lock);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 77d0ee0d125..cd8a58396d2 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -30,12 +30,85 @@ static void _hna_global_del_orig(struct bat_priv *bat_priv,
30 struct hna_global_entry *hna_global_entry, 30 struct hna_global_entry *hna_global_entry,
31 char *message); 31 char *message);
32 32
33/* returns 1 if they are the same mac addr */
34static int compare_lhna(struct hlist_node *node, void *data2)
35{
36 void *data1 = container_of(node, struct hna_local_entry, hash_entry);
37
38 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
39}
40
41/* returns 1 if they are the same mac addr */
42static int compare_ghna(struct hlist_node *node, void *data2)
43{
44 void *data1 = container_of(node, struct hna_global_entry, hash_entry);
45
46 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
47}
48
33static void hna_local_start_timer(struct bat_priv *bat_priv) 49static void hna_local_start_timer(struct bat_priv *bat_priv)
34{ 50{
35 INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge); 51 INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge);
36 queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ); 52 queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ);
37} 53}
38 54
55static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv,
56 void *data)
57{
58 struct hashtable_t *hash = bat_priv->hna_local_hash;
59 struct hlist_head *head;
60 struct hlist_node *node;
61 struct hna_local_entry *hna_local_entry, *hna_local_entry_tmp = NULL;
62 int index;
63
64 if (!hash)
65 return NULL;
66
67 index = choose_orig(data, hash->size);
68 head = &hash->table[index];
69
70 rcu_read_lock();
71 hlist_for_each_entry_rcu(hna_local_entry, node, head, hash_entry) {
72 if (!compare_eth(hna_local_entry, data))
73 continue;
74
75 hna_local_entry_tmp = hna_local_entry;
76 break;
77 }
78 rcu_read_unlock();
79
80 return hna_local_entry_tmp;
81}
82
83static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv,
84 void *data)
85{
86 struct hashtable_t *hash = bat_priv->hna_global_hash;
87 struct hlist_head *head;
88 struct hlist_node *node;
89 struct hna_global_entry *hna_global_entry;
90 struct hna_global_entry *hna_global_entry_tmp = NULL;
91 int index;
92
93 if (!hash)
94 return NULL;
95
96 index = choose_orig(data, hash->size);
97 head = &hash->table[index];
98
99 rcu_read_lock();
100 hlist_for_each_entry_rcu(hna_global_entry, node, head, hash_entry) {
101 if (!compare_eth(hna_global_entry, data))
102 continue;
103
104 hna_global_entry_tmp = hna_global_entry;
105 break;
106 }
107 rcu_read_unlock();
108
109 return hna_global_entry_tmp;
110}
111
39int hna_local_init(struct bat_priv *bat_priv) 112int hna_local_init(struct bat_priv *bat_priv)
40{ 113{
41 if (bat_priv->hna_local_hash) 114 if (bat_priv->hna_local_hash)
@@ -60,12 +133,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
60 int required_bytes; 133 int required_bytes;
61 134
62 spin_lock_bh(&bat_priv->hna_lhash_lock); 135 spin_lock_bh(&bat_priv->hna_lhash_lock);
63 rcu_read_lock(); 136 hna_local_entry = hna_local_hash_find(bat_priv, addr);
64 hna_local_entry =
65 ((struct hna_local_entry *)hash_find(bat_priv->hna_local_hash,
66 compare_orig, choose_orig,
67 addr));
68 rcu_read_unlock();
69 spin_unlock_bh(&bat_priv->hna_lhash_lock); 137 spin_unlock_bh(&bat_priv->hna_lhash_lock);
70 138
71 if (hna_local_entry) { 139 if (hna_local_entry) {
@@ -108,8 +176,8 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
108 176
109 spin_lock_bh(&bat_priv->hna_lhash_lock); 177 spin_lock_bh(&bat_priv->hna_lhash_lock);
110 178
111 hash_add(bat_priv->hna_local_hash, compare_orig, choose_orig, 179 hash_add(bat_priv->hna_local_hash, compare_lhna, choose_orig,
112 hna_local_entry); 180 hna_local_entry, &hna_local_entry->hash_entry);
113 bat_priv->num_local_hna++; 181 bat_priv->num_local_hna++;
114 atomic_set(&bat_priv->hna_local_changed, 1); 182 atomic_set(&bat_priv->hna_local_changed, 1);
115 183
@@ -118,11 +186,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
118 /* remove address from global hash if present */ 186 /* remove address from global hash if present */
119 spin_lock_bh(&bat_priv->hna_ghash_lock); 187 spin_lock_bh(&bat_priv->hna_ghash_lock);
120 188
121 rcu_read_lock(); 189 hna_global_entry = hna_global_hash_find(bat_priv, addr);
122 hna_global_entry = ((struct hna_global_entry *)
123 hash_find(bat_priv->hna_global_hash,
124 compare_orig, choose_orig, addr));
125 rcu_read_unlock();
126 190
127 if (hna_global_entry) 191 if (hna_global_entry)
128 _hna_global_del_orig(bat_priv, hna_global_entry, 192 _hna_global_del_orig(bat_priv, hna_global_entry,
@@ -136,28 +200,27 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv,
136{ 200{
137 struct hashtable_t *hash = bat_priv->hna_local_hash; 201 struct hashtable_t *hash = bat_priv->hna_local_hash;
138 struct hna_local_entry *hna_local_entry; 202 struct hna_local_entry *hna_local_entry;
139 struct element_t *bucket; 203 struct hlist_node *node;
140 int i;
141 struct hlist_node *walk;
142 struct hlist_head *head; 204 struct hlist_head *head;
143 int count = 0; 205 int i, count = 0;
144 206
145 spin_lock_bh(&bat_priv->hna_lhash_lock); 207 spin_lock_bh(&bat_priv->hna_lhash_lock);
146 208
147 for (i = 0; i < hash->size; i++) { 209 for (i = 0; i < hash->size; i++) {
148 head = &hash->table[i]; 210 head = &hash->table[i];
149 211
150 hlist_for_each_entry(bucket, walk, head, hlist) { 212 rcu_read_lock();
151 213 hlist_for_each_entry_rcu(hna_local_entry, node,
214 head, hash_entry) {
152 if (buff_len < (count + 1) * ETH_ALEN) 215 if (buff_len < (count + 1) * ETH_ALEN)
153 break; 216 break;
154 217
155 hna_local_entry = bucket->data;
156 memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr, 218 memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr,
157 ETH_ALEN); 219 ETH_ALEN);
158 220
159 count++; 221 count++;
160 } 222 }
223 rcu_read_unlock();
161 } 224 }
162 225
163 /* if we did not get all new local hnas see you next time ;-) */ 226 /* if we did not get all new local hnas see you next time ;-) */
@@ -174,12 +237,11 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
174 struct bat_priv *bat_priv = netdev_priv(net_dev); 237 struct bat_priv *bat_priv = netdev_priv(net_dev);
175 struct hashtable_t *hash = bat_priv->hna_local_hash; 238 struct hashtable_t *hash = bat_priv->hna_local_hash;
176 struct hna_local_entry *hna_local_entry; 239 struct hna_local_entry *hna_local_entry;
177 int i; 240 struct hlist_node *node;
178 struct hlist_node *walk;
179 struct hlist_head *head; 241 struct hlist_head *head;
180 struct element_t *bucket;
181 size_t buf_size, pos; 242 size_t buf_size, pos;
182 char *buff; 243 char *buff;
244 int i;
183 245
184 if (!bat_priv->primary_if) { 246 if (!bat_priv->primary_if) {
185 return seq_printf(seq, "BATMAN mesh %s disabled - " 247 return seq_printf(seq, "BATMAN mesh %s disabled - "
@@ -198,8 +260,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
198 for (i = 0; i < hash->size; i++) { 260 for (i = 0; i < hash->size; i++) {
199 head = &hash->table[i]; 261 head = &hash->table[i];
200 262
201 hlist_for_each(walk, head) 263 rcu_read_lock();
264 __hlist_for_each_rcu(node, head)
202 buf_size += 21; 265 buf_size += 21;
266 rcu_read_unlock();
203 } 267 }
204 268
205 buff = kmalloc(buf_size, GFP_ATOMIC); 269 buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -207,18 +271,20 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
207 spin_unlock_bh(&bat_priv->hna_lhash_lock); 271 spin_unlock_bh(&bat_priv->hna_lhash_lock);
208 return -ENOMEM; 272 return -ENOMEM;
209 } 273 }
274
210 buff[0] = '\0'; 275 buff[0] = '\0';
211 pos = 0; 276 pos = 0;
212 277
213 for (i = 0; i < hash->size; i++) { 278 for (i = 0; i < hash->size; i++) {
214 head = &hash->table[i]; 279 head = &hash->table[i];
215 280
216 hlist_for_each_entry(bucket, walk, head, hlist) { 281 rcu_read_lock();
217 hna_local_entry = bucket->data; 282 hlist_for_each_entry_rcu(hna_local_entry, node,
218 283 head, hash_entry) {
219 pos += snprintf(buff + pos, 22, " * %pM\n", 284 pos += snprintf(buff + pos, 22, " * %pM\n",
220 hna_local_entry->addr); 285 hna_local_entry->addr);
221 } 286 }
287 rcu_read_unlock();
222 } 288 }
223 289
224 spin_unlock_bh(&bat_priv->hna_lhash_lock); 290 spin_unlock_bh(&bat_priv->hna_lhash_lock);
@@ -228,9 +294,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
228 return 0; 294 return 0;
229} 295}
230 296
231static void _hna_local_del(void *data, void *arg) 297static void _hna_local_del(struct hlist_node *node, void *arg)
232{ 298{
233 struct bat_priv *bat_priv = (struct bat_priv *)arg; 299 struct bat_priv *bat_priv = (struct bat_priv *)arg;
300 void *data = container_of(node, struct hna_local_entry, hash_entry);
234 301
235 kfree(data); 302 kfree(data);
236 bat_priv->num_local_hna--; 303 bat_priv->num_local_hna--;
@@ -244,9 +311,9 @@ static void hna_local_del(struct bat_priv *bat_priv,
244 bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n", 311 bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n",
245 hna_local_entry->addr, message); 312 hna_local_entry->addr, message);
246 313
247 hash_remove(bat_priv->hna_local_hash, compare_orig, choose_orig, 314 hash_remove(bat_priv->hna_local_hash, compare_lhna, choose_orig,
248 hna_local_entry->addr); 315 hna_local_entry->addr);
249 _hna_local_del(hna_local_entry, bat_priv); 316 _hna_local_del(&hna_local_entry->hash_entry, bat_priv);
250} 317}
251 318
252void hna_local_remove(struct bat_priv *bat_priv, 319void hna_local_remove(struct bat_priv *bat_priv,
@@ -256,11 +323,7 @@ void hna_local_remove(struct bat_priv *bat_priv,
256 323
257 spin_lock_bh(&bat_priv->hna_lhash_lock); 324 spin_lock_bh(&bat_priv->hna_lhash_lock);
258 325
259 rcu_read_lock(); 326 hna_local_entry = hna_local_hash_find(bat_priv, addr);
260 hna_local_entry = (struct hna_local_entry *)
261 hash_find(bat_priv->hna_local_hash, compare_orig, choose_orig,
262 addr);
263 rcu_read_unlock();
264 327
265 if (hna_local_entry) 328 if (hna_local_entry)
266 hna_local_del(bat_priv, hna_local_entry, message); 329 hna_local_del(bat_priv, hna_local_entry, message);
@@ -276,27 +339,29 @@ static void hna_local_purge(struct work_struct *work)
276 container_of(delayed_work, struct bat_priv, hna_work); 339 container_of(delayed_work, struct bat_priv, hna_work);
277 struct hashtable_t *hash = bat_priv->hna_local_hash; 340 struct hashtable_t *hash = bat_priv->hna_local_hash;
278 struct hna_local_entry *hna_local_entry; 341 struct hna_local_entry *hna_local_entry;
279 int i; 342 struct hlist_node *node, *node_tmp;
280 struct hlist_node *walk, *safe;
281 struct hlist_head *head; 343 struct hlist_head *head;
282 struct element_t *bucket;
283 unsigned long timeout; 344 unsigned long timeout;
345 int i;
284 346
285 spin_lock_bh(&bat_priv->hna_lhash_lock); 347 spin_lock_bh(&bat_priv->hna_lhash_lock);
286 348
287 for (i = 0; i < hash->size; i++) { 349 for (i = 0; i < hash->size; i++) {
288 head = &hash->table[i]; 350 head = &hash->table[i];
289 351
290 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 352 hlist_for_each_entry_safe(hna_local_entry, node, node_tmp,
291 hna_local_entry = bucket->data; 353 head, hash_entry) {
354 if (hna_local_entry->never_purge)
355 continue;
292 356
293 timeout = hna_local_entry->last_seen; 357 timeout = hna_local_entry->last_seen;
294 timeout += LOCAL_HNA_TIMEOUT * HZ; 358 timeout += LOCAL_HNA_TIMEOUT * HZ;
295 359
296 if ((!hna_local_entry->never_purge) && 360 if (time_before(jiffies, timeout))
297 time_after(jiffies, timeout)) 361 continue;
298 hna_local_del(bat_priv, hna_local_entry, 362
299 "address timed out"); 363 hna_local_del(bat_priv, hna_local_entry,
364 "address timed out");
300 } 365 }
301 } 366 }
302 367
@@ -340,11 +405,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
340 spin_lock_bh(&bat_priv->hna_ghash_lock); 405 spin_lock_bh(&bat_priv->hna_ghash_lock);
341 406
342 hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); 407 hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
343 rcu_read_lock(); 408 hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr);
344 hna_global_entry = (struct hna_global_entry *)
345 hash_find(bat_priv->hna_global_hash, compare_orig,
346 choose_orig, hna_ptr);
347 rcu_read_unlock();
348 409
349 if (!hna_global_entry) { 410 if (!hna_global_entry) {
350 spin_unlock_bh(&bat_priv->hna_ghash_lock); 411 spin_unlock_bh(&bat_priv->hna_ghash_lock);
@@ -364,8 +425,9 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
364 hna_global_entry->addr, orig_node->orig); 425 hna_global_entry->addr, orig_node->orig);
365 426
366 spin_lock_bh(&bat_priv->hna_ghash_lock); 427 spin_lock_bh(&bat_priv->hna_ghash_lock);
367 hash_add(bat_priv->hna_global_hash, compare_orig, 428 hash_add(bat_priv->hna_global_hash, compare_ghna,
368 choose_orig, hna_global_entry); 429 choose_orig, hna_global_entry,
430 &hna_global_entry->hash_entry);
369 431
370 } 432 }
371 433
@@ -376,11 +438,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
376 spin_lock_bh(&bat_priv->hna_lhash_lock); 438 spin_lock_bh(&bat_priv->hna_lhash_lock);
377 439
378 hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); 440 hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
379 rcu_read_lock(); 441 hna_local_entry = hna_local_hash_find(bat_priv, hna_ptr);
380 hna_local_entry = (struct hna_local_entry *)
381 hash_find(bat_priv->hna_local_hash, compare_orig,
382 choose_orig, hna_ptr);
383 rcu_read_unlock();
384 442
385 if (hna_local_entry) 443 if (hna_local_entry)
386 hna_local_del(bat_priv, hna_local_entry, 444 hna_local_del(bat_priv, hna_local_entry,
@@ -410,12 +468,11 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
410 struct bat_priv *bat_priv = netdev_priv(net_dev); 468 struct bat_priv *bat_priv = netdev_priv(net_dev);
411 struct hashtable_t *hash = bat_priv->hna_global_hash; 469 struct hashtable_t *hash = bat_priv->hna_global_hash;
412 struct hna_global_entry *hna_global_entry; 470 struct hna_global_entry *hna_global_entry;
413 int i; 471 struct hlist_node *node;
414 struct hlist_node *walk;
415 struct hlist_head *head; 472 struct hlist_head *head;
416 struct element_t *bucket;
417 size_t buf_size, pos; 473 size_t buf_size, pos;
418 char *buff; 474 char *buff;
475 int i;
419 476
420 if (!bat_priv->primary_if) { 477 if (!bat_priv->primary_if) {
421 return seq_printf(seq, "BATMAN mesh %s disabled - " 478 return seq_printf(seq, "BATMAN mesh %s disabled - "
@@ -433,8 +490,10 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
433 for (i = 0; i < hash->size; i++) { 490 for (i = 0; i < hash->size; i++) {
434 head = &hash->table[i]; 491 head = &hash->table[i];
435 492
436 hlist_for_each(walk, head) 493 rcu_read_lock();
494 __hlist_for_each_rcu(node, head)
437 buf_size += 43; 495 buf_size += 43;
496 rcu_read_unlock();
438 } 497 }
439 498
440 buff = kmalloc(buf_size, GFP_ATOMIC); 499 buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -448,14 +507,15 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
448 for (i = 0; i < hash->size; i++) { 507 for (i = 0; i < hash->size; i++) {
449 head = &hash->table[i]; 508 head = &hash->table[i];
450 509
451 hlist_for_each_entry(bucket, walk, head, hlist) { 510 rcu_read_lock();
452 hna_global_entry = bucket->data; 511 hlist_for_each_entry_rcu(hna_global_entry, node,
453 512 head, hash_entry) {
454 pos += snprintf(buff + pos, 44, 513 pos += snprintf(buff + pos, 44,
455 " * %pM via %pM\n", 514 " * %pM via %pM\n",
456 hna_global_entry->addr, 515 hna_global_entry->addr,
457 hna_global_entry->orig_node->orig); 516 hna_global_entry->orig_node->orig);
458 } 517 }
518 rcu_read_unlock();
459 } 519 }
460 520
461 spin_unlock_bh(&bat_priv->hna_ghash_lock); 521 spin_unlock_bh(&bat_priv->hna_ghash_lock);
@@ -474,7 +534,7 @@ static void _hna_global_del_orig(struct bat_priv *bat_priv,
474 hna_global_entry->addr, hna_global_entry->orig_node->orig, 534 hna_global_entry->addr, hna_global_entry->orig_node->orig,
475 message); 535 message);
476 536
477 hash_remove(bat_priv->hna_global_hash, compare_orig, choose_orig, 537 hash_remove(bat_priv->hna_global_hash, compare_ghna, choose_orig,
478 hna_global_entry->addr); 538 hna_global_entry->addr);
479 kfree(hna_global_entry); 539 kfree(hna_global_entry);
480} 540}
@@ -493,11 +553,7 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
493 553
494 while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) { 554 while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) {
495 hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN); 555 hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN);
496 rcu_read_lock(); 556 hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr);
497 hna_global_entry = (struct hna_global_entry *)
498 hash_find(bat_priv->hna_global_hash, compare_orig,
499 choose_orig, hna_ptr);
500 rcu_read_unlock();
501 557
502 if ((hna_global_entry) && 558 if ((hna_global_entry) &&
503 (hna_global_entry->orig_node == orig_node)) 559 (hna_global_entry->orig_node == orig_node))
@@ -514,8 +570,10 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
514 orig_node->hna_buff = NULL; 570 orig_node->hna_buff = NULL;
515} 571}
516 572
517static void hna_global_del(void *data, void *arg) 573static void hna_global_del(struct hlist_node *node, void *arg)
518{ 574{
575 void *data = container_of(node, struct hna_global_entry, hash_entry);
576
519 kfree(data); 577 kfree(data);
520} 578}
521 579
@@ -533,11 +591,11 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
533 struct hna_global_entry *hna_global_entry; 591 struct hna_global_entry *hna_global_entry;
534 592
535 spin_lock_bh(&bat_priv->hna_ghash_lock); 593 spin_lock_bh(&bat_priv->hna_ghash_lock);
536 rcu_read_lock(); 594 hna_global_entry = hna_global_hash_find(bat_priv, addr);
537 hna_global_entry = (struct hna_global_entry *) 595
538 hash_find(bat_priv->hna_global_hash, 596 if (hna_global_entry)
539 compare_orig, choose_orig, addr); 597 kref_get(&hna_global_entry->orig_node->refcount);
540 rcu_read_unlock(); 598
541 spin_unlock_bh(&bat_priv->hna_ghash_lock); 599 spin_unlock_bh(&bat_priv->hna_ghash_lock);
542 600
543 if (!hna_global_entry) 601 if (!hna_global_entry)
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 3dd5e77a0aa..40365b81bc4 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -85,6 +85,7 @@ struct orig_node {
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 struct kref refcount;
88 struct hlist_node hash_entry;
88 struct bat_priv *bat_priv; 89 struct bat_priv *bat_priv;
89 unsigned long last_frag_packet; 90 unsigned long last_frag_packet;
90 spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum, 91 spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum,
@@ -194,11 +195,13 @@ struct hna_local_entry {
194 uint8_t addr[ETH_ALEN]; 195 uint8_t addr[ETH_ALEN];
195 unsigned long last_seen; 196 unsigned long last_seen;
196 char never_purge; 197 char never_purge;
198 struct hlist_node hash_entry;
197}; 199};
198 200
199struct hna_global_entry { 201struct hna_global_entry {
200 uint8_t addr[ETH_ALEN]; 202 uint8_t addr[ETH_ALEN];
201 struct orig_node *orig_node; 203 struct orig_node *orig_node;
204 struct hlist_node hash_entry;
202}; 205};
203 206
204/** 207/**
@@ -248,6 +251,7 @@ struct vis_info {
248 * from. we should not reply to them. */ 251 * from. we should not reply to them. */
249 struct list_head send_list; 252 struct list_head send_list;
250 struct kref refcount; 253 struct kref refcount;
254 struct hlist_node hash_entry;
251 struct bat_priv *bat_priv; 255 struct bat_priv *bat_priv;
252 /* this packet might be part of the vis send queue. */ 256 /* this packet might be part of the vis send queue. */
253 struct sk_buff *skb_packet; 257 struct sk_buff *skb_packet;
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 0603ceaeef6..2d5daac5203 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -178,17 +178,11 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
178 (struct unicast_frag_packet *)skb->data; 178 (struct unicast_frag_packet *)skb->data;
179 179
180 *new_skb = NULL; 180 *new_skb = NULL;
181
181 spin_lock_bh(&bat_priv->orig_hash_lock); 182 spin_lock_bh(&bat_priv->orig_hash_lock);
182 rcu_read_lock(); 183 orig_node = orig_hash_find(bat_priv, unicast_packet->orig);
183 orig_node = ((struct orig_node *) 184 if (!orig_node)
184 hash_find(bat_priv->orig_hash, compare_orig, choose_orig, 185 goto unlock;
185 unicast_packet->orig));
186 rcu_read_unlock();
187
188 if (!orig_node) {
189 pr_debug("couldn't find originator in orig_hash\n");
190 goto out;
191 }
192 186
193 orig_node->last_frag_packet = jiffies; 187 orig_node->last_frag_packet = jiffies;
194 188
@@ -212,9 +206,12 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
212 /* if not, merge failed */ 206 /* if not, merge failed */
213 if (*new_skb) 207 if (*new_skb)
214 ret = NET_RX_SUCCESS; 208 ret = NET_RX_SUCCESS;
215out:
216 spin_unlock_bh(&bat_priv->orig_hash_lock);
217 209
210unlock:
211 spin_unlock_bh(&bat_priv->orig_hash_lock);
212out:
213 if (orig_node)
214 kref_put(&orig_node->refcount, orig_node_free_ref);
218 return ret; 215 return ret;
219} 216}
220 217
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index fc9732967db..d179acabb04 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -67,11 +67,12 @@ static void free_info(struct kref *ref)
67} 67}
68 68
69/* Compare two vis packets, used by the hashing algorithm */ 69/* Compare two vis packets, used by the hashing algorithm */
70static int vis_info_cmp(void *data1, void *data2) 70static int vis_info_cmp(struct hlist_node *node, void *data2)
71{ 71{
72 struct vis_info *d1, *d2; 72 struct vis_info *d1, *d2;
73 struct vis_packet *p1, *p2; 73 struct vis_packet *p1, *p2;
74 d1 = data1; 74
75 d1 = container_of(node, struct vis_info, hash_entry);
75 d2 = data2; 76 d2 = data2;
76 p1 = (struct vis_packet *)d1->skb_packet->data; 77 p1 = (struct vis_packet *)d1->skb_packet->data;
77 p2 = (struct vis_packet *)d2->skb_packet->data; 78 p2 = (struct vis_packet *)d2->skb_packet->data;
@@ -103,6 +104,34 @@ static int vis_info_choose(void *data, int size)
103 return hash % size; 104 return hash % size;
104} 105}
105 106
107static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
108 void *data)
109{
110 struct hashtable_t *hash = bat_priv->vis_hash;
111 struct hlist_head *head;
112 struct hlist_node *node;
113 struct vis_info *vis_info, *vis_info_tmp = NULL;
114 int index;
115
116 if (!hash)
117 return NULL;
118
119 index = vis_info_choose(data, hash->size);
120 head = &hash->table[index];
121
122 rcu_read_lock();
123 hlist_for_each_entry_rcu(vis_info, node, head, hash_entry) {
124 if (!vis_info_cmp(node, data))
125 continue;
126
127 vis_info_tmp = vis_info;
128 break;
129 }
130 rcu_read_unlock();
131
132 return vis_info_tmp;
133}
134
106/* insert interface to the list of interfaces of one originator, if it 135/* insert interface to the list of interfaces of one originator, if it
107 * does not already exist in the list */ 136 * does not already exist in the list */
108static void vis_data_insert_interface(const uint8_t *interface, 137static void vis_data_insert_interface(const uint8_t *interface,
@@ -174,9 +203,8 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
174 203
175int vis_seq_print_text(struct seq_file *seq, void *offset) 204int vis_seq_print_text(struct seq_file *seq, void *offset)
176{ 205{
177 struct hlist_node *walk; 206 struct hlist_node *node;
178 struct hlist_head *head; 207 struct hlist_head *head;
179 struct element_t *bucket;
180 struct vis_info *info; 208 struct vis_info *info;
181 struct vis_packet *packet; 209 struct vis_packet *packet;
182 struct vis_info_entry *entries; 210 struct vis_info_entry *entries;
@@ -202,8 +230,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
202 for (i = 0; i < hash->size; i++) { 230 for (i = 0; i < hash->size; i++) {
203 head = &hash->table[i]; 231 head = &hash->table[i];
204 232
205 hlist_for_each_entry(bucket, walk, head, hlist) { 233 rcu_read_lock();
206 info = bucket->data; 234 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
207 packet = (struct vis_packet *)info->skb_packet->data; 235 packet = (struct vis_packet *)info->skb_packet->data;
208 entries = (struct vis_info_entry *) 236 entries = (struct vis_info_entry *)
209 ((char *)packet + sizeof(struct vis_packet)); 237 ((char *)packet + sizeof(struct vis_packet));
@@ -235,6 +263,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
235 kfree(entry); 263 kfree(entry);
236 } 264 }
237 } 265 }
266 rcu_read_unlock();
238 } 267 }
239 268
240 buff = kmalloc(buf_size, GFP_ATOMIC); 269 buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -248,8 +277,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
248 for (i = 0; i < hash->size; i++) { 277 for (i = 0; i < hash->size; i++) {
249 head = &hash->table[i]; 278 head = &hash->table[i];
250 279
251 hlist_for_each_entry(bucket, walk, head, hlist) { 280 rcu_read_lock();
252 info = bucket->data; 281 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
253 packet = (struct vis_packet *)info->skb_packet->data; 282 packet = (struct vis_packet *)info->skb_packet->data;
254 entries = (struct vis_info_entry *) 283 entries = (struct vis_info_entry *)
255 ((char *)packet + sizeof(struct vis_packet)); 284 ((char *)packet + sizeof(struct vis_packet));
@@ -290,6 +319,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
290 kfree(entry); 319 kfree(entry);
291 } 320 }
292 } 321 }
322 rcu_read_unlock();
293 } 323 }
294 324
295 spin_unlock_bh(&bat_priv->vis_hash_lock); 325 spin_unlock_bh(&bat_priv->vis_hash_lock);
@@ -380,10 +410,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
380 sizeof(struct vis_packet)); 410 sizeof(struct vis_packet));
381 411
382 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN); 412 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
383 rcu_read_lock(); 413 old_info = vis_hash_find(bat_priv, &search_elem);
384 old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
385 &search_elem);
386 rcu_read_unlock();
387 kfree_skb(search_elem.skb_packet); 414 kfree_skb(search_elem.skb_packet);
388 415
389 if (old_info) { 416 if (old_info) {
@@ -443,7 +470,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
443 470
444 /* try to add it */ 471 /* try to add it */
445 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 472 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
446 info); 473 info, &info->hash_entry);
447 if (hash_added < 0) { 474 if (hash_added < 0) {
448 /* did not work (for some reason) */ 475 /* did not work (for some reason) */
449 kref_put(&old_info->refcount, free_info); 476 kref_put(&old_info->refcount, free_info);
@@ -530,9 +557,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
530 struct vis_info *info) 557 struct vis_info *info)
531{ 558{
532 struct hashtable_t *hash = bat_priv->orig_hash; 559 struct hashtable_t *hash = bat_priv->orig_hash;
533 struct hlist_node *walk; 560 struct hlist_node *node;
534 struct hlist_head *head; 561 struct hlist_head *head;
535 struct element_t *bucket;
536 struct orig_node *orig_node; 562 struct orig_node *orig_node;
537 struct vis_packet *packet; 563 struct vis_packet *packet;
538 int best_tq = -1, i; 564 int best_tq = -1, i;
@@ -543,11 +569,10 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
543 head = &hash->table[i]; 569 head = &hash->table[i];
544 570
545 rcu_read_lock(); 571 rcu_read_lock();
546 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 572 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
547 orig_node = bucket->data;
548 if ((orig_node) && (orig_node->router) && 573 if ((orig_node) && (orig_node->router) &&
549 (orig_node->flags & VIS_SERVER) && 574 (orig_node->flags & VIS_SERVER) &&
550 (orig_node->router->tq_avg > best_tq)) { 575 (orig_node->router->tq_avg > best_tq)) {
551 best_tq = orig_node->router->tq_avg; 576 best_tq = orig_node->router->tq_avg;
552 memcpy(packet->target_orig, orig_node->orig, 577 memcpy(packet->target_orig, orig_node->orig,
553 ETH_ALEN); 578 ETH_ALEN);
@@ -576,9 +601,8 @@ static bool vis_packet_full(struct vis_info *info)
576static int generate_vis_packet(struct bat_priv *bat_priv) 601static int generate_vis_packet(struct bat_priv *bat_priv)
577{ 602{
578 struct hashtable_t *hash = bat_priv->orig_hash; 603 struct hashtable_t *hash = bat_priv->orig_hash;
579 struct hlist_node *walk; 604 struct hlist_node *node;
580 struct hlist_head *head; 605 struct hlist_head *head;
581 struct element_t *bucket;
582 struct orig_node *orig_node; 606 struct orig_node *orig_node;
583 struct neigh_node *neigh_node; 607 struct neigh_node *neigh_node;
584 struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; 608 struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
@@ -610,8 +634,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
610 head = &hash->table[i]; 634 head = &hash->table[i];
611 635
612 rcu_read_lock(); 636 rcu_read_lock();
613 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 637 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
614 orig_node = bucket->data;
615 neigh_node = orig_node->router; 638 neigh_node = orig_node->router;
616 639
617 if (!neigh_node) 640 if (!neigh_node)
@@ -653,8 +676,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
653 for (i = 0; i < hash->size; i++) { 676 for (i = 0; i < hash->size; i++) {
654 head = &hash->table[i]; 677 head = &hash->table[i];
655 678
656 hlist_for_each_entry(bucket, walk, head, hlist) { 679 hlist_for_each_entry(hna_local_entry, node, head, hash_entry) {
657 hna_local_entry = bucket->data;
658 entry = (struct vis_info_entry *) 680 entry = (struct vis_info_entry *)
659 skb_put(info->skb_packet, 681 skb_put(info->skb_packet,
660 sizeof(*entry)); 682 sizeof(*entry));
@@ -680,25 +702,22 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
680{ 702{
681 int i; 703 int i;
682 struct hashtable_t *hash = bat_priv->vis_hash; 704 struct hashtable_t *hash = bat_priv->vis_hash;
683 struct hlist_node *walk, *safe; 705 struct hlist_node *node, *node_tmp;
684 struct hlist_head *head; 706 struct hlist_head *head;
685 struct element_t *bucket;
686 struct vis_info *info; 707 struct vis_info *info;
687 708
688 for (i = 0; i < hash->size; i++) { 709 for (i = 0; i < hash->size; i++) {
689 head = &hash->table[i]; 710 head = &hash->table[i];
690 711
691 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 712 hlist_for_each_entry_safe(info, node, node_tmp,
692 info = bucket->data; 713 head, hash_entry) {
693
694 /* never purge own data. */ 714 /* never purge own data. */
695 if (info == bat_priv->my_vis_info) 715 if (info == bat_priv->my_vis_info)
696 continue; 716 continue;
697 717
698 if (time_after(jiffies, 718 if (time_after(jiffies,
699 info->first_seen + VIS_TIMEOUT * HZ)) { 719 info->first_seen + VIS_TIMEOUT * HZ)) {
700 hlist_del(walk); 720 hlist_del(node);
701 kfree(bucket);
702 send_list_del(info); 721 send_list_del(info);
703 kref_put(&info->refcount, free_info); 722 kref_put(&info->refcount, free_info);
704 } 723 }
@@ -710,9 +729,8 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
710 struct vis_info *info) 729 struct vis_info *info)
711{ 730{
712 struct hashtable_t *hash = bat_priv->orig_hash; 731 struct hashtable_t *hash = bat_priv->orig_hash;
713 struct hlist_node *walk; 732 struct hlist_node *node;
714 struct hlist_head *head; 733 struct hlist_head *head;
715 struct element_t *bucket;
716 struct orig_node *orig_node; 734 struct orig_node *orig_node;
717 struct vis_packet *packet; 735 struct vis_packet *packet;
718 struct sk_buff *skb; 736 struct sk_buff *skb;
@@ -729,9 +747,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
729 head = &hash->table[i]; 747 head = &hash->table[i];
730 748
731 rcu_read_lock(); 749 rcu_read_lock();
732 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 750 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
733 orig_node = bucket->data;
734
735 /* if it's a vis server and reachable, send it. */ 751 /* if it's a vis server and reachable, send it. */
736 if ((!orig_node) || (!orig_node->router)) 752 if ((!orig_node) || (!orig_node->router))
737 continue; 753 continue;
@@ -774,14 +790,11 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
774 790
775 spin_lock_bh(&bat_priv->orig_hash_lock); 791 spin_lock_bh(&bat_priv->orig_hash_lock);
776 rcu_read_lock(); 792 rcu_read_lock();
777 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 793 orig_node = orig_hash_find(bat_priv, packet->target_orig);
778 compare_orig, choose_orig,
779 packet->target_orig));
780 794
781 if (!orig_node) 795 if (!orig_node)
782 goto unlock; 796 goto unlock;
783 797
784 kref_get(&orig_node->refcount);
785 neigh_node = orig_node->router; 798 neigh_node = orig_node->router;
786 799
787 if (!neigh_node) 800 if (!neigh_node)
@@ -925,7 +938,8 @@ int vis_init(struct bat_priv *bat_priv)
925 INIT_LIST_HEAD(&bat_priv->vis_send_list); 938 INIT_LIST_HEAD(&bat_priv->vis_send_list);
926 939
927 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 940 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
928 bat_priv->my_vis_info); 941 bat_priv->my_vis_info,
942 &bat_priv->my_vis_info->hash_entry);
929 if (hash_added < 0) { 943 if (hash_added < 0) {
930 pr_err("Can't add own vis packet into hash\n"); 944 pr_err("Can't add own vis packet into hash\n");
931 /* not in hash, need to remove it manually. */ 945 /* not in hash, need to remove it manually. */
@@ -947,10 +961,11 @@ err:
947} 961}
948 962
949/* Decrease the reference count on a hash item info */ 963/* Decrease the reference count on a hash item info */
950static void free_info_ref(void *data, void *arg) 964static void free_info_ref(struct hlist_node *node, void *arg)
951{ 965{
952 struct vis_info *info = data; 966 struct vis_info *info;
953 967
968 info = container_of(node, struct vis_info, hash_entry);
954 send_list_del(info); 969 send_list_del(info);
955 kref_put(&info->refcount, free_info); 970 kref_put(&info->refcount, free_info);
956} 971}