diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2010-12-12 16:57:12 -0500 |
---|---|---|
committer | Marek Lindner <lindner_marek@yahoo.de> | 2011-03-05 06:49:54 -0500 |
commit | f987ed6ebd991009cd9f6190ce319e8b50d6be1f (patch) | |
tree | 08fd4c5edc6ee74407ec901cef960978946f716f /net/batman-adv/routing.c | |
parent | 9591a79f280ede740e44aeb8ad93a6692d482dce (diff) |
batman-adv: protect neighbor list with rcu locks
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r-- | net/batman-adv/routing.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index e8379ba25e95..97f321615686 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -153,14 +153,16 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
153 | unsigned char total_count; | 153 | unsigned char total_count; |
154 | 154 | ||
155 | if (orig_node == orig_neigh_node) { | 155 | if (orig_node == orig_neigh_node) { |
156 | hlist_for_each_entry(tmp_neigh_node, node, | 156 | rcu_read_lock(); |
157 | &orig_node->neigh_list, list) { | 157 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
158 | &orig_node->neigh_list, list) { | ||
158 | 159 | ||
159 | if (compare_orig(tmp_neigh_node->addr, | 160 | if (compare_orig(tmp_neigh_node->addr, |
160 | orig_neigh_node->orig) && | 161 | orig_neigh_node->orig) && |
161 | (tmp_neigh_node->if_incoming == if_incoming)) | 162 | (tmp_neigh_node->if_incoming == if_incoming)) |
162 | neigh_node = tmp_neigh_node; | 163 | neigh_node = tmp_neigh_node; |
163 | } | 164 | } |
165 | rcu_read_unlock(); | ||
164 | 166 | ||
165 | if (!neigh_node) | 167 | if (!neigh_node) |
166 | neigh_node = create_neighbor(orig_node, | 168 | neigh_node = create_neighbor(orig_node, |
@@ -174,14 +176,16 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
174 | neigh_node->last_valid = jiffies; | 176 | neigh_node->last_valid = jiffies; |
175 | } else { | 177 | } else { |
176 | /* find packet count of corresponding one hop neighbor */ | 178 | /* find packet count of corresponding one hop neighbor */ |
177 | hlist_for_each_entry(tmp_neigh_node, node, | 179 | rcu_read_lock(); |
178 | &orig_neigh_node->neigh_list, list) { | 180 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
181 | &orig_neigh_node->neigh_list, list) { | ||
179 | 182 | ||
180 | if (compare_orig(tmp_neigh_node->addr, | 183 | if (compare_orig(tmp_neigh_node->addr, |
181 | orig_neigh_node->orig) && | 184 | orig_neigh_node->orig) && |
182 | (tmp_neigh_node->if_incoming == if_incoming)) | 185 | (tmp_neigh_node->if_incoming == if_incoming)) |
183 | neigh_node = tmp_neigh_node; | 186 | neigh_node = tmp_neigh_node; |
184 | } | 187 | } |
188 | rcu_read_unlock(); | ||
185 | 189 | ||
186 | if (!neigh_node) | 190 | if (!neigh_node) |
187 | neigh_node = create_neighbor(orig_neigh_node, | 191 | neigh_node = create_neighbor(orig_neigh_node, |
@@ -266,8 +270,9 @@ static void update_orig(struct bat_priv *bat_priv, | |||
266 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " | 270 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " |
267 | "Searching and updating originator entry of received packet\n"); | 271 | "Searching and updating originator entry of received packet\n"); |
268 | 272 | ||
269 | hlist_for_each_entry(tmp_neigh_node, node, | 273 | rcu_read_lock(); |
270 | &orig_node->neigh_list, list) { | 274 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
275 | &orig_node->neigh_list, list) { | ||
271 | if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && | 276 | if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && |
272 | (tmp_neigh_node->if_incoming == if_incoming)) { | 277 | (tmp_neigh_node->if_incoming == if_incoming)) { |
273 | neigh_node = tmp_neigh_node; | 278 | neigh_node = tmp_neigh_node; |
@@ -282,6 +287,7 @@ static void update_orig(struct bat_priv *bat_priv, | |||
282 | tmp_neigh_node->tq_avg = | 287 | tmp_neigh_node->tq_avg = |
283 | ring_buffer_avg(tmp_neigh_node->tq_recv); | 288 | ring_buffer_avg(tmp_neigh_node->tq_recv); |
284 | } | 289 | } |
290 | rcu_read_unlock(); | ||
285 | 291 | ||
286 | if (!neigh_node) { | 292 | if (!neigh_node) { |
287 | struct orig_node *orig_tmp; | 293 | struct orig_node *orig_tmp; |
@@ -410,8 +416,9 @@ static char count_real_packets(struct ethhdr *ethhdr, | |||
410 | &orig_node->batman_seqno_reset)) | 416 | &orig_node->batman_seqno_reset)) |
411 | return -1; | 417 | return -1; |
412 | 418 | ||
413 | hlist_for_each_entry(tmp_neigh_node, node, | 419 | rcu_read_lock(); |
414 | &orig_node->neigh_list, list) { | 420 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
421 | &orig_node->neigh_list, list) { | ||
415 | 422 | ||
416 | is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, | 423 | is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, |
417 | orig_node->last_real_seqno, | 424 | orig_node->last_real_seqno, |
@@ -431,6 +438,7 @@ static char count_real_packets(struct ethhdr *ethhdr, | |||
431 | tmp_neigh_node->real_packet_count = | 438 | tmp_neigh_node->real_packet_count = |
432 | bit_packet_count(tmp_neigh_node->real_bits); | 439 | bit_packet_count(tmp_neigh_node->real_bits); |
433 | } | 440 | } |
441 | rcu_read_unlock(); | ||
434 | 442 | ||
435 | if (need_update) { | 443 | if (need_update) { |
436 | bat_dbg(DBG_BATMAN, bat_priv, | 444 | bat_dbg(DBG_BATMAN, bat_priv, |
@@ -481,15 +489,19 @@ void update_bonding_candidates(struct orig_node *orig_node) | |||
481 | * as "bonding partner" */ | 489 | * as "bonding partner" */ |
482 | 490 | ||
483 | /* first, zero the list */ | 491 | /* first, zero the list */ |
484 | hlist_for_each_entry(tmp_neigh_node, node, | 492 | rcu_read_lock(); |
485 | &orig_node->neigh_list, list) { | 493 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
494 | &orig_node->neigh_list, list) { | ||
486 | tmp_neigh_node->next_bond_candidate = NULL; | 495 | tmp_neigh_node->next_bond_candidate = NULL; |
487 | } | 496 | } |
497 | rcu_read_unlock(); | ||
488 | 498 | ||
489 | first_candidate = NULL; | 499 | first_candidate = NULL; |
490 | last_candidate = NULL; | 500 | last_candidate = NULL; |
491 | hlist_for_each_entry(tmp_neigh_node, node, | 501 | |
492 | &orig_node->neigh_list, list) { | 502 | rcu_read_lock(); |
503 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | ||
504 | &orig_node->neigh_list, list) { | ||
493 | 505 | ||
494 | /* only consider if it has the same primary address ... */ | 506 | /* only consider if it has the same primary address ... */ |
495 | if (memcmp(orig_node->orig, | 507 | if (memcmp(orig_node->orig, |
@@ -506,8 +518,8 @@ void update_bonding_candidates(struct orig_node *orig_node) | |||
506 | * select this candidate because of possible interference. */ | 518 | * select this candidate because of possible interference. */ |
507 | 519 | ||
508 | interference_candidate = 0; | 520 | interference_candidate = 0; |
509 | hlist_for_each_entry(tmp_neigh_node2, node2, | 521 | hlist_for_each_entry_rcu(tmp_neigh_node2, node2, |
510 | &orig_node->neigh_list, list) { | 522 | &orig_node->neigh_list, list) { |
511 | 523 | ||
512 | if (tmp_neigh_node2 == tmp_neigh_node) | 524 | if (tmp_neigh_node2 == tmp_neigh_node) |
513 | continue; | 525 | continue; |
@@ -541,6 +553,7 @@ void update_bonding_candidates(struct orig_node *orig_node) | |||
541 | 553 | ||
542 | candidates++; | 554 | candidates++; |
543 | } | 555 | } |
556 | rcu_read_unlock(); | ||
544 | 557 | ||
545 | if (candidates > 0) { | 558 | if (candidates > 0) { |
546 | first_candidate->next_bond_candidate = last_candidate; | 559 | first_candidate->next_bond_candidate = last_candidate; |