diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-11-04 08:43:23 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-04 08:43:23 -0500 |
commit | c6d14c84566d6b70ad9dc1618db0dec87cca9300 (patch) | |
tree | 5ec75245cfda4d61e6b4506b6217f047ff4af01a /net/ipv6 | |
parent | d0075634cf9d288988f57392a1f132d2053af961 (diff) |
net: Introduce for_each_netdev_rcu() iterator
Adds RCU management to the list of netdevices.
Convert some for_each_netdev() users to RCU version, if
it can avoid read_lock-ing dev_base_lock
Ie:
read_lock(&dev_base_loack);
for_each_netdev(net, dev)
some_action();
read_unlock(&dev_base_lock);
becomes :
rcu_read_lock();
for_each_netdev_rcu(net, dev)
some_action();
rcu_read_unlock();
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 20 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 6 |
2 files changed, 10 insertions, 16 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 918648409612..024bba30de21 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -481,9 +481,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
481 | struct net_device *dev; | 481 | struct net_device *dev; |
482 | struct inet6_dev *idev; | 482 | struct inet6_dev *idev; |
483 | 483 | ||
484 | read_lock(&dev_base_lock); | 484 | rcu_read_lock(); |
485 | for_each_netdev(net, dev) { | 485 | for_each_netdev_rcu(net, dev) { |
486 | rcu_read_lock(); | ||
487 | idev = __in6_dev_get(dev); | 486 | idev = __in6_dev_get(dev); |
488 | if (idev) { | 487 | if (idev) { |
489 | int changed = (!idev->cnf.forwarding) ^ (!newf); | 488 | int changed = (!idev->cnf.forwarding) ^ (!newf); |
@@ -491,9 +490,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
491 | if (changed) | 490 | if (changed) |
492 | dev_forward_change(idev); | 491 | dev_forward_change(idev); |
493 | } | 492 | } |
494 | rcu_read_unlock(); | ||
495 | } | 493 | } |
496 | read_unlock(&dev_base_lock); | 494 | rcu_read_unlock(); |
497 | } | 495 | } |
498 | 496 | ||
499 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | 497 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) |
@@ -1137,10 +1135,9 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
1137 | hiscore->rule = -1; | 1135 | hiscore->rule = -1; |
1138 | hiscore->ifa = NULL; | 1136 | hiscore->ifa = NULL; |
1139 | 1137 | ||
1140 | read_lock(&dev_base_lock); | ||
1141 | rcu_read_lock(); | 1138 | rcu_read_lock(); |
1142 | 1139 | ||
1143 | for_each_netdev(net, dev) { | 1140 | for_each_netdev_rcu(net, dev) { |
1144 | struct inet6_dev *idev; | 1141 | struct inet6_dev *idev; |
1145 | 1142 | ||
1146 | /* Candidate Source Address (section 4) | 1143 | /* Candidate Source Address (section 4) |
@@ -1235,7 +1232,6 @@ try_nextdev: | |||
1235 | read_unlock_bh(&idev->lock); | 1232 | read_unlock_bh(&idev->lock); |
1236 | } | 1233 | } |
1237 | rcu_read_unlock(); | 1234 | rcu_read_unlock(); |
1238 | read_unlock(&dev_base_lock); | ||
1239 | 1235 | ||
1240 | if (!hiscore->ifa) | 1236 | if (!hiscore->ifa) |
1241 | return -EADDRNOTAVAIL; | 1237 | return -EADDRNOTAVAIL; |
@@ -4052,9 +4048,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) | |||
4052 | struct net_device *dev; | 4048 | struct net_device *dev; |
4053 | struct inet6_dev *idev; | 4049 | struct inet6_dev *idev; |
4054 | 4050 | ||
4055 | read_lock(&dev_base_lock); | 4051 | rcu_read_lock(); |
4056 | for_each_netdev(net, dev) { | 4052 | for_each_netdev_rcu(net, dev) { |
4057 | rcu_read_lock(); | ||
4058 | idev = __in6_dev_get(dev); | 4053 | idev = __in6_dev_get(dev); |
4059 | if (idev) { | 4054 | if (idev) { |
4060 | int changed = (!idev->cnf.disable_ipv6) ^ (!newf); | 4055 | int changed = (!idev->cnf.disable_ipv6) ^ (!newf); |
@@ -4062,9 +4057,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) | |||
4062 | if (changed) | 4057 | if (changed) |
4063 | dev_disable_change(idev); | 4058 | dev_disable_change(idev); |
4064 | } | 4059 | } |
4065 | rcu_read_unlock(); | ||
4066 | } | 4060 | } |
4067 | read_unlock(&dev_base_lock); | 4061 | rcu_read_unlock(); |
4068 | } | 4062 | } |
4069 | 4063 | ||
4070 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) | 4064 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 1ae58bec1de0..2f00ca83f049 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -404,13 +404,13 @@ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | |||
404 | 404 | ||
405 | if (dev) | 405 | if (dev) |
406 | return ipv6_chk_acast_dev(dev, addr); | 406 | return ipv6_chk_acast_dev(dev, addr); |
407 | read_lock(&dev_base_lock); | 407 | rcu_read_lock(); |
408 | for_each_netdev(net, dev) | 408 | for_each_netdev_rcu(net, dev) |
409 | if (ipv6_chk_acast_dev(dev, addr)) { | 409 | if (ipv6_chk_acast_dev(dev, addr)) { |
410 | found = 1; | 410 | found = 1; |
411 | break; | 411 | break; |
412 | } | 412 | } |
413 | read_unlock(&dev_base_lock); | 413 | rcu_read_unlock(); |
414 | return found; | 414 | return found; |
415 | } | 415 | } |
416 | 416 | ||