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.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 899d4943d8ad..5c32314f8279 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -150,9 +150,11 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
150 int size; 150 int size;
151 int hash_added; 151 int hash_added;
152 152
153 rcu_read_lock();
153 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 154 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
154 compare_orig, choose_orig, 155 compare_orig, choose_orig,
155 addr)); 156 addr));
157 rcu_read_unlock();
156 158
157 if (orig_node) 159 if (orig_node)
158 return orig_node; 160 return orig_node;
@@ -294,6 +296,7 @@ static void _purge_orig(struct bat_priv *bat_priv)
294 struct hlist_node *walk, *safe; 296 struct hlist_node *walk, *safe;
295 struct hlist_head *head; 297 struct hlist_head *head;
296 struct element_t *bucket; 298 struct element_t *bucket;
299 spinlock_t *list_lock; /* spinlock to protect write access */
297 struct orig_node *orig_node; 300 struct orig_node *orig_node;
298 int i; 301 int i;
299 302
@@ -305,22 +308,26 @@ static void _purge_orig(struct bat_priv *bat_priv)
305 /* for all origins... */ 308 /* for all origins... */
306 for (i = 0; i < hash->size; i++) { 309 for (i = 0; i < hash->size; i++) {
307 head = &hash->table[i]; 310 head = &hash->table[i];
311 list_lock = &hash->list_locks[i];
308 312
313 spin_lock_bh(list_lock);
309 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 314 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) {
310 orig_node = bucket->data; 315 orig_node = bucket->data;
311 316
312 if (purge_orig_node(bat_priv, orig_node)) { 317 if (purge_orig_node(bat_priv, orig_node)) {
313 if (orig_node->gw_flags) 318 if (orig_node->gw_flags)
314 gw_node_delete(bat_priv, orig_node); 319 gw_node_delete(bat_priv, orig_node);
315 hlist_del(walk); 320 hlist_del_rcu(walk);
316 kfree(bucket); 321 call_rcu(&bucket->rcu, bucket_free_rcu);
317 free_orig_node(orig_node, bat_priv); 322 free_orig_node(orig_node, bat_priv);
323 continue;
318 } 324 }
319 325
320 if (time_after(jiffies, orig_node->last_frag_packet + 326 if (time_after(jiffies, orig_node->last_frag_packet +
321 msecs_to_jiffies(FRAG_TIMEOUT))) 327 msecs_to_jiffies(FRAG_TIMEOUT)))
322 frag_list_free(&orig_node->frag_list); 328 frag_list_free(&orig_node->frag_list);
323 } 329 }
330 spin_unlock_bh(list_lock);
324 } 331 }
325 332
326 spin_unlock_bh(&bat_priv->orig_hash_lock); 333 spin_unlock_bh(&bat_priv->orig_hash_lock);
@@ -387,7 +394,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
387 for (i = 0; i < hash->size; i++) { 394 for (i = 0; i < hash->size; i++) {
388 head = &hash->table[i]; 395 head = &hash->table[i];
389 396
390 hlist_for_each_entry(bucket, walk, head, hlist) { 397 rcu_read_lock();
398 hlist_for_each_entry_rcu(bucket, walk, head, hlist) {
391 orig_node = bucket->data; 399 orig_node = bucket->data;
392 400
393 if (!orig_node->router) 401 if (!orig_node->router)
@@ -408,17 +416,16 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
408 neigh_node->addr, 416 neigh_node->addr,
409 neigh_node->if_incoming->net_dev->name); 417 neigh_node->if_incoming->net_dev->name);
410 418
411 rcu_read_lock();
412 hlist_for_each_entry_rcu(neigh_node, node, 419 hlist_for_each_entry_rcu(neigh_node, node,
413 &orig_node->neigh_list, list) { 420 &orig_node->neigh_list, list) {
414 seq_printf(seq, " %pM (%3i)", neigh_node->addr, 421 seq_printf(seq, " %pM (%3i)", neigh_node->addr,
415 neigh_node->tq_avg); 422 neigh_node->tq_avg);
416 } 423 }
417 rcu_read_unlock();
418 424
419 seq_printf(seq, "\n"); 425 seq_printf(seq, "\n");
420 batman_count++; 426 batman_count++;
421 } 427 }
428 rcu_read_unlock();
422 } 429 }
423 430
424 spin_unlock_bh(&bat_priv->orig_hash_lock); 431 spin_unlock_bh(&bat_priv->orig_hash_lock);
@@ -476,18 +483,21 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
476 for (i = 0; i < hash->size; i++) { 483 for (i = 0; i < hash->size; i++) {
477 head = &hash->table[i]; 484 head = &hash->table[i];
478 485
479 hlist_for_each_entry(bucket, walk, head, hlist) { 486 rcu_read_lock();
487 hlist_for_each_entry_rcu(bucket, walk, head, hlist) {
480 orig_node = bucket->data; 488 orig_node = bucket->data;
481 489
482 if (orig_node_add_if(orig_node, max_if_num) == -1) 490 if (orig_node_add_if(orig_node, max_if_num) == -1)
483 goto err; 491 goto err;
484 } 492 }
493 rcu_read_unlock();
485 } 494 }
486 495
487 spin_unlock_bh(&bat_priv->orig_hash_lock); 496 spin_unlock_bh(&bat_priv->orig_hash_lock);
488 return 0; 497 return 0;
489 498
490err: 499err:
500 rcu_read_unlock();
491 spin_unlock_bh(&bat_priv->orig_hash_lock); 501 spin_unlock_bh(&bat_priv->orig_hash_lock);
492 return -ENOMEM; 502 return -ENOMEM;
493} 503}
@@ -562,7 +572,8 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
562 for (i = 0; i < hash->size; i++) { 572 for (i = 0; i < hash->size; i++) {
563 head = &hash->table[i]; 573 head = &hash->table[i];
564 574
565 hlist_for_each_entry(bucket, walk, head, hlist) { 575 rcu_read_lock();
576 hlist_for_each_entry_rcu(bucket, walk, head, hlist) {
566 orig_node = bucket->data; 577 orig_node = bucket->data;
567 578
568 ret = orig_node_del_if(orig_node, max_if_num, 579 ret = orig_node_del_if(orig_node, max_if_num,
@@ -571,6 +582,7 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
571 if (ret == -1) 582 if (ret == -1)
572 goto err; 583 goto err;
573 } 584 }
585 rcu_read_unlock();
574 } 586 }
575 587
576 /* renumber remaining batman interfaces _inside_ of orig_hash_lock */ 588 /* renumber remaining batman interfaces _inside_ of orig_hash_lock */
@@ -595,6 +607,7 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
595 return 0; 607 return 0;
596 608
597err: 609err:
610 rcu_read_unlock();
598 spin_unlock_bh(&bat_priv->orig_hash_lock); 611 spin_unlock_bh(&bat_priv->orig_hash_lock);
599 return -ENOMEM; 612 return -ENOMEM;
600} 613}