aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/anycast.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-11-11 12:34:30 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-13 23:38:49 -0500
commitce81b76a39835a721cd168e0c0bcfe7132f1f66b (patch)
treeed725dd6163f328d4717fb3ed28c9e6c2691bc88 /net/ipv6/anycast.c
parentbee7ca9ec03a26676ea2b1c28dc4039348eff3e1 (diff)
ipv6: use RCU to walk list of network devices
No longer need read_lock(&dev_base_lock), use RCU instead. We also can avoid taking references on inet6_dev structs. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/anycast.c')
-rw-r--r--net/ipv6/anycast.c29
1 files changed, 14 insertions, 15 deletions
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 2f00ca83f049..f1c74c8ef9de 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -431,9 +431,9 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
431 struct net *net = seq_file_net(seq); 431 struct net *net = seq_file_net(seq);
432 432
433 state->idev = NULL; 433 state->idev = NULL;
434 for_each_netdev(net, state->dev) { 434 for_each_netdev_rcu(net, state->dev) {
435 struct inet6_dev *idev; 435 struct inet6_dev *idev;
436 idev = in6_dev_get(state->dev); 436 idev = __in6_dev_get(state->dev);
437 if (!idev) 437 if (!idev)
438 continue; 438 continue;
439 read_lock_bh(&idev->lock); 439 read_lock_bh(&idev->lock);
@@ -443,7 +443,6 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
443 break; 443 break;
444 } 444 }
445 read_unlock_bh(&idev->lock); 445 read_unlock_bh(&idev->lock);
446 in6_dev_put(idev);
447 } 446 }
448 return im; 447 return im;
449} 448}
@@ -454,16 +453,15 @@ static struct ifacaddr6 *ac6_get_next(struct seq_file *seq, struct ifacaddr6 *im
454 453
455 im = im->aca_next; 454 im = im->aca_next;
456 while (!im) { 455 while (!im) {
457 if (likely(state->idev != NULL)) { 456 if (likely(state->idev != NULL))
458 read_unlock_bh(&state->idev->lock); 457 read_unlock_bh(&state->idev->lock);
459 in6_dev_put(state->idev); 458
460 } 459 state->dev = next_net_device_rcu(state->dev);
461 state->dev = next_net_device(state->dev);
462 if (!state->dev) { 460 if (!state->dev) {
463 state->idev = NULL; 461 state->idev = NULL;
464 break; 462 break;
465 } 463 }
466 state->idev = in6_dev_get(state->dev); 464 state->idev = __in6_dev_get(state->dev);
467 if (!state->idev) 465 if (!state->idev)
468 continue; 466 continue;
469 read_lock_bh(&state->idev->lock); 467 read_lock_bh(&state->idev->lock);
@@ -482,29 +480,30 @@ static struct ifacaddr6 *ac6_get_idx(struct seq_file *seq, loff_t pos)
482} 480}
483 481
484static void *ac6_seq_start(struct seq_file *seq, loff_t *pos) 482static void *ac6_seq_start(struct seq_file *seq, loff_t *pos)
485 __acquires(dev_base_lock) 483 __acquires(RCU)
486{ 484{
487 read_lock(&dev_base_lock); 485 rcu_read_lock();
488 return ac6_get_idx(seq, *pos); 486 return ac6_get_idx(seq, *pos);
489} 487}
490 488
491static void *ac6_seq_next(struct seq_file *seq, void *v, loff_t *pos) 489static void *ac6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
492{ 490{
493 struct ifacaddr6 *im; 491 struct ifacaddr6 *im = ac6_get_next(seq, v);
494 im = ac6_get_next(seq, v); 492
495 ++*pos; 493 ++*pos;
496 return im; 494 return im;
497} 495}
498 496
499static void ac6_seq_stop(struct seq_file *seq, void *v) 497static void ac6_seq_stop(struct seq_file *seq, void *v)
500 __releases(dev_base_lock) 498 __releases(RCU)
501{ 499{
502 struct ac6_iter_state *state = ac6_seq_private(seq); 500 struct ac6_iter_state *state = ac6_seq_private(seq);
501
503 if (likely(state->idev != NULL)) { 502 if (likely(state->idev != NULL)) {
504 read_unlock_bh(&state->idev->lock); 503 read_unlock_bh(&state->idev->lock);
505 in6_dev_put(state->idev); 504 state->idev = NULL;
506 } 505 }
507 read_unlock(&dev_base_lock); 506 rcu_read_unlock();
508} 507}
509 508
510static int ac6_seq_show(struct seq_file *seq, void *v) 509static int ac6_seq_show(struct seq_file *seq, void *v)