diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2011-02-18 07:28:09 -0500 |
---|---|---|
committer | Marek Lindner <lindner_marek@yahoo.de> | 2011-03-05 06:52:00 -0500 |
commit | 7aadf889e897155c45cda230d2a6701ad1fbff61 (patch) | |
tree | 4a31df411c29844afe25ccde17d2ff9e618241c1 /net/batman-adv | |
parent | 39901e716275da4e831b40f9e45a1b61d6a776dc (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.c | 8 | ||||
-rw-r--r-- | net/batman-adv/hash.h | 95 | ||||
-rw-r--r-- | net/batman-adv/icmp_socket.c | 5 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 73 | ||||
-rw-r--r-- | net/batman-adv/originator.h | 35 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 40 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 208 | ||||
-rw-r--r-- | net/batman-adv/types.h | 4 | ||||
-rw-r--r-- | net/batman-adv/unicast.c | 21 | ||||
-rw-r--r-- | net/batman-adv/vis.c | 103 |
10 files changed, 298 insertions, 294 deletions
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c index 02653666a26b..c5213d8f2cca 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 | |||
72 | void 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 3c48c6bb1acd..434822b27473 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 */ |
31 | typedef int (*hashdata_compare_cb)(void *, void *); | 31 | typedef 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 */ |
36 | typedef int (*hashdata_choose_cb)(void *, int); | 36 | typedef int (*hashdata_choose_cb)(void *, int); |
37 | typedef void (*hashdata_free_cb)(void *, void *); | 37 | typedef void (*hashdata_free_cb)(struct hlist_node *, void *); |
38 | |||
39 | struct 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 | ||
45 | struct hashtable_t { | 39 | struct 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. */ |
55 | void hash_destroy(struct hashtable_t *hash); | 49 | void hash_destroy(struct hashtable_t *hash); |
56 | 50 | ||
57 | void 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 */ |
90 | static inline int hash_add(struct hashtable_t *hash, | 80 | static 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 | **/ | ||
170 | static 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 7fa5bb8a9409..139b7336adf9 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 d9a8e316c249..bdcb399329dd 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) | |||
140 | void originator_free(struct bat_priv *bat_priv) | 140 | void 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 | ||
177 | static 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 */ |
191 | struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) | 177 | struct 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, | |||
346 | static void _purge_orig(struct bat_priv *bat_priv) | 325 | static 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 84d96e2eea47..b4b9a09259fd 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 | |||
25 | int originator_init(struct bat_priv *bat_priv); | 27 | int originator_init(struct bat_priv *bat_priv); |
26 | void originator_free(struct bat_priv *bat_priv); | 28 | void originator_free(struct bat_priv *bat_priv); |
27 | void purge_orig_ref(struct bat_priv *bat_priv); | 29 | void 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 */ |
41 | static inline int compare_orig(void *data1, void *data2) | 43 | static 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 | ||
71 | static 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 b54bf6ec637e..fc4c12a049da 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 77d0ee0d1257..cd8a58396d26 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 */ | ||
34 | static 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 */ | ||
42 | static 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 | |||
33 | static void hna_local_start_timer(struct bat_priv *bat_priv) | 49 | static 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 | ||
55 | static 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 | |||
83 | static 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 | |||
39 | int hna_local_init(struct bat_priv *bat_priv) | 112 | int 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 | ||
231 | static void _hna_local_del(void *data, void *arg) | 297 | static 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 | ||
252 | void hna_local_remove(struct bat_priv *bat_priv, | 319 | void 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 | ||
517 | static void hna_global_del(void *data, void *arg) | 573 | static 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 3dd5e77a0aa0..40365b81bc40 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 | ||
199 | struct hna_global_entry { | 201 | struct 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 0603ceaeef62..2d5daac52034 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; |
215 | out: | ||
216 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
217 | 209 | ||
210 | unlock: | ||
211 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
212 | out: | ||
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 fc9732967dbd..d179acabb04c 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 */ |
70 | static int vis_info_cmp(void *data1, void *data2) | 70 | static 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 | ||
107 | static 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 */ |
108 | static void vis_data_insert_interface(const uint8_t *interface, | 137 | static 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 | ||
175 | int vis_seq_print_text(struct seq_file *seq, void *offset) | 204 | int 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) | |||
576 | static int generate_vis_packet(struct bat_priv *bat_priv) | 601 | static 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 */ |
950 | static void free_info_ref(void *data, void *arg) | 964 | static 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 | } |