aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/originator.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/originator.c')
-rw-r--r--net/batman-adv/originator.c254
1 files changed, 158 insertions, 96 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 6b7fb6b7e6f..0b9133022d2 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors: 2 * Copyright (C) 2009-2011 B.A.T.M.A.N. contributors:
3 * 3 *
4 * Marek Lindner, Simon Wunderlich 4 * Marek Lindner, Simon Wunderlich
5 * 5 *
@@ -44,24 +44,36 @@ int originator_init(struct bat_priv *bat_priv)
44 if (bat_priv->orig_hash) 44 if (bat_priv->orig_hash)
45 return 1; 45 return 1;
46 46
47 spin_lock_bh(&bat_priv->orig_hash_lock);
48 bat_priv->orig_hash = hash_new(1024); 47 bat_priv->orig_hash = hash_new(1024);
49 48
50 if (!bat_priv->orig_hash) 49 if (!bat_priv->orig_hash)
51 goto err; 50 goto err;
52 51
53 spin_unlock_bh(&bat_priv->orig_hash_lock);
54 start_purge_timer(bat_priv); 52 start_purge_timer(bat_priv);
55 return 1; 53 return 1;
56 54
57err: 55err:
58 spin_unlock_bh(&bat_priv->orig_hash_lock);
59 return 0; 56 return 0;
60} 57}
61 58
62struct neigh_node * 59static void neigh_node_free_rcu(struct rcu_head *rcu)
63create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, 60{
64 uint8_t *neigh, struct batman_if *if_incoming) 61 struct neigh_node *neigh_node;
62
63 neigh_node = container_of(rcu, struct neigh_node, rcu);
64 kfree(neigh_node);
65}
66
67void neigh_node_free_ref(struct neigh_node *neigh_node)
68{
69 if (atomic_dec_and_test(&neigh_node->refcount))
70 call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
71}
72
73struct neigh_node *create_neighbor(struct orig_node *orig_node,
74 struct orig_node *orig_neigh_node,
75 uint8_t *neigh,
76 struct hard_iface *if_incoming)
65{ 77{
66 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 78 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
67 struct neigh_node *neigh_node; 79 struct neigh_node *neigh_node;
@@ -73,50 +85,94 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
73 if (!neigh_node) 85 if (!neigh_node)
74 return NULL; 86 return NULL;
75 87
76 INIT_LIST_HEAD(&neigh_node->list); 88 INIT_HLIST_NODE(&neigh_node->list);
89 INIT_LIST_HEAD(&neigh_node->bonding_list);
77 90
78 memcpy(neigh_node->addr, neigh, ETH_ALEN); 91 memcpy(neigh_node->addr, neigh, ETH_ALEN);
79 neigh_node->orig_node = orig_neigh_node; 92 neigh_node->orig_node = orig_neigh_node;
80 neigh_node->if_incoming = if_incoming; 93 neigh_node->if_incoming = if_incoming;
81 94
82 list_add_tail(&neigh_node->list, &orig_node->neigh_list); 95 /* extra reference for return */
96 atomic_set(&neigh_node->refcount, 2);
97
98 spin_lock_bh(&orig_node->neigh_list_lock);
99 hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
100 spin_unlock_bh(&orig_node->neigh_list_lock);
83 return neigh_node; 101 return neigh_node;
84} 102}
85 103
86static void free_orig_node(void *data, void *arg) 104static void orig_node_free_rcu(struct rcu_head *rcu)
87{ 105{
88 struct list_head *list_pos, *list_pos_tmp; 106 struct hlist_node *node, *node_tmp;
89 struct neigh_node *neigh_node; 107 struct neigh_node *neigh_node, *tmp_neigh_node;
90 struct orig_node *orig_node = (struct orig_node *)data; 108 struct orig_node *orig_node;
91 struct bat_priv *bat_priv = (struct bat_priv *)arg;
92 109
93 /* for all neighbors towards this originator ... */ 110 orig_node = container_of(rcu, struct orig_node, rcu);
94 list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 111
95 neigh_node = list_entry(list_pos, struct neigh_node, list); 112 spin_lock_bh(&orig_node->neigh_list_lock);
113
114 /* for all bonding members ... */
115 list_for_each_entry_safe(neigh_node, tmp_neigh_node,
116 &orig_node->bond_list, bonding_list) {
117 list_del_rcu(&neigh_node->bonding_list);
118 neigh_node_free_ref(neigh_node);
119 }
96 120
97 list_del(list_pos); 121 /* for all neighbors towards this originator ... */
98 kfree(neigh_node); 122 hlist_for_each_entry_safe(neigh_node, node, node_tmp,
123 &orig_node->neigh_list, list) {
124 hlist_del_rcu(&neigh_node->list);
125 neigh_node_free_ref(neigh_node);
99 } 126 }
100 127
128 spin_unlock_bh(&orig_node->neigh_list_lock);
129
101 frag_list_free(&orig_node->frag_list); 130 frag_list_free(&orig_node->frag_list);
102 hna_global_del_orig(bat_priv, orig_node, "originator timed out"); 131 hna_global_del_orig(orig_node->bat_priv, orig_node,
132 "originator timed out");
103 133
104 kfree(orig_node->bcast_own); 134 kfree(orig_node->bcast_own);
105 kfree(orig_node->bcast_own_sum); 135 kfree(orig_node->bcast_own_sum);
106 kfree(orig_node); 136 kfree(orig_node);
107} 137}
108 138
139void orig_node_free_ref(struct orig_node *orig_node)
140{
141 if (atomic_dec_and_test(&orig_node->refcount))
142 call_rcu(&orig_node->rcu, orig_node_free_rcu);
143}
144
109void originator_free(struct bat_priv *bat_priv) 145void originator_free(struct bat_priv *bat_priv)
110{ 146{
111 if (!bat_priv->orig_hash) 147 struct hashtable_t *hash = bat_priv->orig_hash;
148 struct hlist_node *node, *node_tmp;
149 struct hlist_head *head;
150 spinlock_t *list_lock; /* spinlock to protect write access */
151 struct orig_node *orig_node;
152 int i;
153
154 if (!hash)
112 return; 155 return;
113 156
114 cancel_delayed_work_sync(&bat_priv->orig_work); 157 cancel_delayed_work_sync(&bat_priv->orig_work);
115 158
116 spin_lock_bh(&bat_priv->orig_hash_lock);
117 hash_delete(bat_priv->orig_hash, free_orig_node, bat_priv);
118 bat_priv->orig_hash = NULL; 159 bat_priv->orig_hash = NULL;
119 spin_unlock_bh(&bat_priv->orig_hash_lock); 160
161 for (i = 0; i < hash->size; i++) {
162 head = &hash->table[i];
163 list_lock = &hash->list_locks[i];
164
165 spin_lock_bh(list_lock);
166 hlist_for_each_entry_safe(orig_node, node, node_tmp,
167 head, hash_entry) {
168
169 hlist_del_rcu(node);
170 orig_node_free_ref(orig_node);
171 }
172 spin_unlock_bh(list_lock);
173 }
174
175 hash_destroy(hash);
120} 176}
121 177
122/* this function finds or creates an originator entry for the given 178/* this function finds or creates an originator entry for the given
@@ -127,10 +183,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
127 int size; 183 int size;
128 int hash_added; 184 int hash_added;
129 185
130 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 186 orig_node = orig_hash_find(bat_priv, addr);
131 compare_orig, choose_orig,
132 addr));
133
134 if (orig_node) 187 if (orig_node)
135 return orig_node; 188 return orig_node;
136 189
@@ -141,8 +194,16 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
141 if (!orig_node) 194 if (!orig_node)
142 return NULL; 195 return NULL;
143 196
144 INIT_LIST_HEAD(&orig_node->neigh_list); 197 INIT_HLIST_HEAD(&orig_node->neigh_list);
198 INIT_LIST_HEAD(&orig_node->bond_list);
199 spin_lock_init(&orig_node->ogm_cnt_lock);
200 spin_lock_init(&orig_node->bcast_seqno_lock);
201 spin_lock_init(&orig_node->neigh_list_lock);
202
203 /* extra reference for return */
204 atomic_set(&orig_node->refcount, 2);
145 205
206 orig_node->bat_priv = bat_priv;
146 memcpy(orig_node->orig, addr, ETH_ALEN); 207 memcpy(orig_node->orig, addr, ETH_ALEN);
147 orig_node->router = NULL; 208 orig_node->router = NULL;
148 orig_node->hna_buff = NULL; 209 orig_node->hna_buff = NULL;
@@ -151,6 +212,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
151 orig_node->batman_seqno_reset = jiffies - 1 212 orig_node->batman_seqno_reset = jiffies - 1
152 - msecs_to_jiffies(RESET_PROTECTION_MS); 213 - msecs_to_jiffies(RESET_PROTECTION_MS);
153 214
215 atomic_set(&orig_node->bond_candidates, 0);
216
154 size = bat_priv->num_ifaces * sizeof(unsigned long) * NUM_WORDS; 217 size = bat_priv->num_ifaces * sizeof(unsigned long) * NUM_WORDS;
155 218
156 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC); 219 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
@@ -166,8 +229,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
166 if (!orig_node->bcast_own_sum) 229 if (!orig_node->bcast_own_sum)
167 goto free_bcast_own; 230 goto free_bcast_own;
168 231
169 hash_added = hash_add(bat_priv->orig_hash, compare_orig, choose_orig, 232 hash_added = hash_add(bat_priv->orig_hash, compare_orig,
170 orig_node); 233 choose_orig, orig_node, &orig_node->hash_entry);
171 if (hash_added < 0) 234 if (hash_added < 0)
172 goto free_bcast_own_sum; 235 goto free_bcast_own_sum;
173 236
@@ -185,23 +248,30 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
185 struct orig_node *orig_node, 248 struct orig_node *orig_node,
186 struct neigh_node **best_neigh_node) 249 struct neigh_node **best_neigh_node)
187{ 250{
188 struct list_head *list_pos, *list_pos_tmp; 251 struct hlist_node *node, *node_tmp;
189 struct neigh_node *neigh_node; 252 struct neigh_node *neigh_node;
190 bool neigh_purged = false; 253 bool neigh_purged = false;
191 254
192 *best_neigh_node = NULL; 255 *best_neigh_node = NULL;
193 256
257 spin_lock_bh(&orig_node->neigh_list_lock);
258
194 /* for all neighbors towards this originator ... */ 259 /* for all neighbors towards this originator ... */
195 list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 260 hlist_for_each_entry_safe(neigh_node, node, node_tmp,
196 neigh_node = list_entry(list_pos, struct neigh_node, list); 261 &orig_node->neigh_list, list) {
197 262
198 if ((time_after(jiffies, 263 if ((time_after(jiffies,
199 neigh_node->last_valid + PURGE_TIMEOUT * HZ)) || 264 neigh_node->last_valid + PURGE_TIMEOUT * HZ)) ||
200 (neigh_node->if_incoming->if_status == IF_INACTIVE) || 265 (neigh_node->if_incoming->if_status == IF_INACTIVE) ||
266 (neigh_node->if_incoming->if_status == IF_NOT_IN_USE) ||
201 (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) { 267 (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) {
202 268
203 if (neigh_node->if_incoming->if_status == 269 if ((neigh_node->if_incoming->if_status ==
204 IF_TO_BE_REMOVED) 270 IF_INACTIVE) ||
271 (neigh_node->if_incoming->if_status ==
272 IF_NOT_IN_USE) ||
273 (neigh_node->if_incoming->if_status ==
274 IF_TO_BE_REMOVED))
205 bat_dbg(DBG_BATMAN, bat_priv, 275 bat_dbg(DBG_BATMAN, bat_priv,
206 "neighbor purge: originator %pM, " 276 "neighbor purge: originator %pM, "
207 "neighbor: %pM, iface: %s\n", 277 "neighbor: %pM, iface: %s\n",
@@ -215,14 +285,18 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
215 (neigh_node->last_valid / HZ)); 285 (neigh_node->last_valid / HZ));
216 286
217 neigh_purged = true; 287 neigh_purged = true;
218 list_del(list_pos); 288
219 kfree(neigh_node); 289 hlist_del_rcu(&neigh_node->list);
290 bonding_candidate_del(orig_node, neigh_node);
291 neigh_node_free_ref(neigh_node);
220 } else { 292 } else {
221 if ((!*best_neigh_node) || 293 if ((!*best_neigh_node) ||
222 (neigh_node->tq_avg > (*best_neigh_node)->tq_avg)) 294 (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
223 *best_neigh_node = neigh_node; 295 *best_neigh_node = neigh_node;
224 } 296 }
225 } 297 }
298
299 spin_unlock_bh(&orig_node->neigh_list_lock);
226 return neigh_purged; 300 return neigh_purged;
227} 301}
228 302
@@ -245,9 +319,6 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
245 best_neigh_node, 319 best_neigh_node,
246 orig_node->hna_buff, 320 orig_node->hna_buff,
247 orig_node->hna_buff_len); 321 orig_node->hna_buff_len);
248 /* update bonding candidates, we could have lost
249 * some candidates. */
250 update_bonding_candidates(bat_priv, orig_node);
251 } 322 }
252 } 323 }
253 324
@@ -257,40 +328,38 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
257static void _purge_orig(struct bat_priv *bat_priv) 328static void _purge_orig(struct bat_priv *bat_priv)
258{ 329{
259 struct hashtable_t *hash = bat_priv->orig_hash; 330 struct hashtable_t *hash = bat_priv->orig_hash;
260 struct hlist_node *walk, *safe; 331 struct hlist_node *node, *node_tmp;
261 struct hlist_head *head; 332 struct hlist_head *head;
262 struct element_t *bucket; 333 spinlock_t *list_lock; /* spinlock to protect write access */
263 struct orig_node *orig_node; 334 struct orig_node *orig_node;
264 int i; 335 int i;
265 336
266 if (!hash) 337 if (!hash)
267 return; 338 return;
268 339
269 spin_lock_bh(&bat_priv->orig_hash_lock);
270
271 /* for all origins... */ 340 /* for all origins... */
272 for (i = 0; i < hash->size; i++) { 341 for (i = 0; i < hash->size; i++) {
273 head = &hash->table[i]; 342 head = &hash->table[i];
343 list_lock = &hash->list_locks[i];
274 344
275 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 345 spin_lock_bh(list_lock);
276 orig_node = bucket->data; 346 hlist_for_each_entry_safe(orig_node, node, node_tmp,
277 347 head, hash_entry) {
278 if (purge_orig_node(bat_priv, orig_node)) { 348 if (purge_orig_node(bat_priv, orig_node)) {
279 if (orig_node->gw_flags) 349 if (orig_node->gw_flags)
280 gw_node_delete(bat_priv, orig_node); 350 gw_node_delete(bat_priv, orig_node);
281 hlist_del(walk); 351 hlist_del_rcu(node);
282 kfree(bucket); 352 orig_node_free_ref(orig_node);
283 free_orig_node(orig_node, bat_priv); 353 continue;
284 } 354 }
285 355
286 if (time_after(jiffies, orig_node->last_frag_packet + 356 if (time_after(jiffies, orig_node->last_frag_packet +
287 msecs_to_jiffies(FRAG_TIMEOUT))) 357 msecs_to_jiffies(FRAG_TIMEOUT)))
288 frag_list_free(&orig_node->frag_list); 358 frag_list_free(&orig_node->frag_list);
289 } 359 }
360 spin_unlock_bh(list_lock);
290 } 361 }
291 362
292 spin_unlock_bh(&bat_priv->orig_hash_lock);
293
294 gw_node_purge(bat_priv); 363 gw_node_purge(bat_priv);
295 gw_election(bat_priv); 364 gw_election(bat_priv);
296 365
@@ -318,9 +387,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
318 struct net_device *net_dev = (struct net_device *)seq->private; 387 struct net_device *net_dev = (struct net_device *)seq->private;
319 struct bat_priv *bat_priv = netdev_priv(net_dev); 388 struct bat_priv *bat_priv = netdev_priv(net_dev);
320 struct hashtable_t *hash = bat_priv->orig_hash; 389 struct hashtable_t *hash = bat_priv->orig_hash;
321 struct hlist_node *walk; 390 struct hlist_node *node, *node_tmp;
322 struct hlist_head *head; 391 struct hlist_head *head;
323 struct element_t *bucket;
324 struct orig_node *orig_node; 392 struct orig_node *orig_node;
325 struct neigh_node *neigh_node; 393 struct neigh_node *neigh_node;
326 int batman_count = 0; 394 int batman_count = 0;
@@ -348,14 +416,11 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
348 "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", 416 "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
349 "outgoingIF", "Potential nexthops"); 417 "outgoingIF", "Potential nexthops");
350 418
351 spin_lock_bh(&bat_priv->orig_hash_lock);
352
353 for (i = 0; i < hash->size; i++) { 419 for (i = 0; i < hash->size; i++) {
354 head = &hash->table[i]; 420 head = &hash->table[i];
355 421
356 hlist_for_each_entry(bucket, walk, head, hlist) { 422 rcu_read_lock();
357 orig_node = bucket->data; 423 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
358
359 if (!orig_node->router) 424 if (!orig_node->router)
360 continue; 425 continue;
361 426
@@ -374,8 +439,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
374 neigh_node->addr, 439 neigh_node->addr,
375 neigh_node->if_incoming->net_dev->name); 440 neigh_node->if_incoming->net_dev->name);
376 441
377 list_for_each_entry(neigh_node, &orig_node->neigh_list, 442 hlist_for_each_entry_rcu(neigh_node, node_tmp,
378 list) { 443 &orig_node->neigh_list, list) {
379 seq_printf(seq, " %pM (%3i)", neigh_node->addr, 444 seq_printf(seq, " %pM (%3i)", neigh_node->addr,
380 neigh_node->tq_avg); 445 neigh_node->tq_avg);
381 } 446 }
@@ -383,10 +448,9 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
383 seq_printf(seq, "\n"); 448 seq_printf(seq, "\n");
384 batman_count++; 449 batman_count++;
385 } 450 }
451 rcu_read_unlock();
386 } 452 }
387 453
388 spin_unlock_bh(&bat_priv->orig_hash_lock);
389
390 if ((batman_count == 0)) 454 if ((batman_count == 0))
391 seq_printf(seq, "No batman nodes in range ...\n"); 455 seq_printf(seq, "No batman nodes in range ...\n");
392 456
@@ -423,36 +487,36 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
423 return 0; 487 return 0;
424} 488}
425 489
426int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) 490int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num)
427{ 491{
428 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); 492 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
429 struct hashtable_t *hash = bat_priv->orig_hash; 493 struct hashtable_t *hash = bat_priv->orig_hash;
430 struct hlist_node *walk; 494 struct hlist_node *node;
431 struct hlist_head *head; 495 struct hlist_head *head;
432 struct element_t *bucket;
433 struct orig_node *orig_node; 496 struct orig_node *orig_node;
434 int i; 497 int i, ret;
435 498
436 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on 499 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
437 * if_num */ 500 * if_num */
438 spin_lock_bh(&bat_priv->orig_hash_lock);
439
440 for (i = 0; i < hash->size; i++) { 501 for (i = 0; i < hash->size; i++) {
441 head = &hash->table[i]; 502 head = &hash->table[i];
442 503
443 hlist_for_each_entry(bucket, walk, head, hlist) { 504 rcu_read_lock();
444 orig_node = bucket->data; 505 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
506 spin_lock_bh(&orig_node->ogm_cnt_lock);
507 ret = orig_node_add_if(orig_node, max_if_num);
508 spin_unlock_bh(&orig_node->ogm_cnt_lock);
445 509
446 if (orig_node_add_if(orig_node, max_if_num) == -1) 510 if (ret == -1)
447 goto err; 511 goto err;
448 } 512 }
513 rcu_read_unlock();
449 } 514 }
450 515
451 spin_unlock_bh(&bat_priv->orig_hash_lock);
452 return 0; 516 return 0;
453 517
454err: 518err:
455 spin_unlock_bh(&bat_priv->orig_hash_lock); 519 rcu_read_unlock();
456 return -ENOMEM; 520 return -ENOMEM;
457} 521}
458 522
@@ -508,57 +572,55 @@ free_own_sum:
508 return 0; 572 return 0;
509} 573}
510 574
511int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) 575int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num)
512{ 576{
513 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); 577 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
514 struct hashtable_t *hash = bat_priv->orig_hash; 578 struct hashtable_t *hash = bat_priv->orig_hash;
515 struct hlist_node *walk; 579 struct hlist_node *node;
516 struct hlist_head *head; 580 struct hlist_head *head;
517 struct element_t *bucket; 581 struct hard_iface *hard_iface_tmp;
518 struct batman_if *batman_if_tmp;
519 struct orig_node *orig_node; 582 struct orig_node *orig_node;
520 int i, ret; 583 int i, ret;
521 584
522 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on 585 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
523 * if_num */ 586 * if_num */
524 spin_lock_bh(&bat_priv->orig_hash_lock);
525
526 for (i = 0; i < hash->size; i++) { 587 for (i = 0; i < hash->size; i++) {
527 head = &hash->table[i]; 588 head = &hash->table[i];
528 589
529 hlist_for_each_entry(bucket, walk, head, hlist) { 590 rcu_read_lock();
530 orig_node = bucket->data; 591 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
531 592 spin_lock_bh(&orig_node->ogm_cnt_lock);
532 ret = orig_node_del_if(orig_node, max_if_num, 593 ret = orig_node_del_if(orig_node, max_if_num,
533 batman_if->if_num); 594 hard_iface->if_num);
595 spin_unlock_bh(&orig_node->ogm_cnt_lock);
534 596
535 if (ret == -1) 597 if (ret == -1)
536 goto err; 598 goto err;
537 } 599 }
600 rcu_read_unlock();
538 } 601 }
539 602
540 /* renumber remaining batman interfaces _inside_ of orig_hash_lock */ 603 /* renumber remaining batman interfaces _inside_ of orig_hash_lock */
541 rcu_read_lock(); 604 rcu_read_lock();
542 list_for_each_entry_rcu(batman_if_tmp, &if_list, list) { 605 list_for_each_entry_rcu(hard_iface_tmp, &hardif_list, list) {
543 if (batman_if_tmp->if_status == IF_NOT_IN_USE) 606 if (hard_iface_tmp->if_status == IF_NOT_IN_USE)
544 continue; 607 continue;
545 608
546 if (batman_if == batman_if_tmp) 609 if (hard_iface == hard_iface_tmp)
547 continue; 610 continue;
548 611
549 if (batman_if->soft_iface != batman_if_tmp->soft_iface) 612 if (hard_iface->soft_iface != hard_iface_tmp->soft_iface)
550 continue; 613 continue;
551 614
552 if (batman_if_tmp->if_num > batman_if->if_num) 615 if (hard_iface_tmp->if_num > hard_iface->if_num)
553 batman_if_tmp->if_num--; 616 hard_iface_tmp->if_num--;
554 } 617 }
555 rcu_read_unlock(); 618 rcu_read_unlock();
556 619
557 batman_if->if_num = -1; 620 hard_iface->if_num = -1;
558 spin_unlock_bh(&bat_priv->orig_hash_lock);
559 return 0; 621 return 0;
560 622
561err: 623err:
562 spin_unlock_bh(&bat_priv->orig_hash_lock); 624 rcu_read_unlock();
563 return -ENOMEM; 625 return -ENOMEM;
564} 626}