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 | |
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>
-rw-r--r-- | include/linux/netdevice.h | 2 | ||||
-rw-r--r-- | net/core/dev.c | 30 | ||||
-rw-r--r-- | net/decnet/af_decnet.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_fib.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 6 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 30 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 20 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 6 | ||||
-rw-r--r-- | net/netrom/nr_route.c | 15 | ||||
-rw-r--r-- | net/rose/rose_route.c | 18 | ||||
-rw-r--r-- | net/sctp/protocol.c | 6 |
11 files changed, 68 insertions, 77 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index bcf1083857fc..5077de028317 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1081,6 +1081,8 @@ extern rwlock_t dev_base_lock; /* Device list lock */ | |||
1081 | 1081 | ||
1082 | #define for_each_netdev(net, d) \ | 1082 | #define for_each_netdev(net, d) \ |
1083 | list_for_each_entry(d, &(net)->dev_base_head, dev_list) | 1083 | list_for_each_entry(d, &(net)->dev_base_head, dev_list) |
1084 | #define for_each_netdev_rcu(net, d) \ | ||
1085 | list_for_each_entry_rcu(d, &(net)->dev_base_head, dev_list) | ||
1084 | #define for_each_netdev_safe(net, d, n) \ | 1086 | #define for_each_netdev_safe(net, d, n) \ |
1085 | list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list) | 1087 | list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list) |
1086 | #define for_each_netdev_continue(net, d) \ | 1088 | #define for_each_netdev_continue(net, d) \ |
diff --git a/net/core/dev.c b/net/core/dev.c index 76a1502efe67..bf629ac08b87 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -175,7 +175,7 @@ static struct list_head ptype_all __read_mostly; /* Taps */ | |||
175 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl | 175 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl |
176 | * semaphore. | 176 | * semaphore. |
177 | * | 177 | * |
178 | * Pure readers hold dev_base_lock for reading. | 178 | * Pure readers hold dev_base_lock for reading, or rcu_read_lock() |
179 | * | 179 | * |
180 | * Writers must hold the rtnl semaphore while they loop through the | 180 | * Writers must hold the rtnl semaphore while they loop through the |
181 | * dev_base_head list, and hold dev_base_lock for writing when they do the | 181 | * dev_base_head list, and hold dev_base_lock for writing when they do the |
@@ -212,7 +212,7 @@ static int list_netdevice(struct net_device *dev) | |||
212 | ASSERT_RTNL(); | 212 | ASSERT_RTNL(); |
213 | 213 | ||
214 | write_lock_bh(&dev_base_lock); | 214 | write_lock_bh(&dev_base_lock); |
215 | list_add_tail(&dev->dev_list, &net->dev_base_head); | 215 | list_add_tail_rcu(&dev->dev_list, &net->dev_base_head); |
216 | hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name)); | 216 | hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name)); |
217 | hlist_add_head_rcu(&dev->index_hlist, | 217 | hlist_add_head_rcu(&dev->index_hlist, |
218 | dev_index_hash(net, dev->ifindex)); | 218 | dev_index_hash(net, dev->ifindex)); |
@@ -229,7 +229,7 @@ static void unlist_netdevice(struct net_device *dev) | |||
229 | 229 | ||
230 | /* Unlink dev from the device chain */ | 230 | /* Unlink dev from the device chain */ |
231 | write_lock_bh(&dev_base_lock); | 231 | write_lock_bh(&dev_base_lock); |
232 | list_del(&dev->dev_list); | 232 | list_del_rcu(&dev->dev_list); |
233 | hlist_del_rcu(&dev->name_hlist); | 233 | hlist_del_rcu(&dev->name_hlist); |
234 | hlist_del_rcu(&dev->index_hlist); | 234 | hlist_del_rcu(&dev->index_hlist); |
235 | write_unlock_bh(&dev_base_lock); | 235 | write_unlock_bh(&dev_base_lock); |
@@ -799,15 +799,15 @@ struct net_device *dev_get_by_flags(struct net *net, unsigned short if_flags, | |||
799 | struct net_device *dev, *ret; | 799 | struct net_device *dev, *ret; |
800 | 800 | ||
801 | ret = NULL; | 801 | ret = NULL; |
802 | read_lock(&dev_base_lock); | 802 | rcu_read_lock(); |
803 | for_each_netdev(net, dev) { | 803 | for_each_netdev_rcu(net, dev) { |
804 | if (((dev->flags ^ if_flags) & mask) == 0) { | 804 | if (((dev->flags ^ if_flags) & mask) == 0) { |
805 | dev_hold(dev); | 805 | dev_hold(dev); |
806 | ret = dev; | 806 | ret = dev; |
807 | break; | 807 | break; |
808 | } | 808 | } |
809 | } | 809 | } |
810 | read_unlock(&dev_base_lock); | 810 | rcu_read_unlock(); |
811 | return ret; | 811 | return ret; |
812 | } | 812 | } |
813 | EXPORT_SYMBOL(dev_get_by_flags); | 813 | EXPORT_SYMBOL(dev_get_by_flags); |
@@ -3077,18 +3077,18 @@ static int dev_ifconf(struct net *net, char __user *arg) | |||
3077 | * in detail. | 3077 | * in detail. |
3078 | */ | 3078 | */ |
3079 | void *dev_seq_start(struct seq_file *seq, loff_t *pos) | 3079 | void *dev_seq_start(struct seq_file *seq, loff_t *pos) |
3080 | __acquires(dev_base_lock) | 3080 | __acquires(RCU) |
3081 | { | 3081 | { |
3082 | struct net *net = seq_file_net(seq); | 3082 | struct net *net = seq_file_net(seq); |
3083 | loff_t off; | 3083 | loff_t off; |
3084 | struct net_device *dev; | 3084 | struct net_device *dev; |
3085 | 3085 | ||
3086 | read_lock(&dev_base_lock); | 3086 | rcu_read_lock(); |
3087 | if (!*pos) | 3087 | if (!*pos) |
3088 | return SEQ_START_TOKEN; | 3088 | return SEQ_START_TOKEN; |
3089 | 3089 | ||
3090 | off = 1; | 3090 | off = 1; |
3091 | for_each_netdev(net, dev) | 3091 | for_each_netdev_rcu(net, dev) |
3092 | if (off++ == *pos) | 3092 | if (off++ == *pos) |
3093 | return dev; | 3093 | return dev; |
3094 | 3094 | ||
@@ -3097,16 +3097,18 @@ void *dev_seq_start(struct seq_file *seq, loff_t *pos) | |||
3097 | 3097 | ||
3098 | void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 3098 | void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
3099 | { | 3099 | { |
3100 | struct net *net = seq_file_net(seq); | 3100 | struct net_device *dev = (v == SEQ_START_TOKEN) ? |
3101 | first_net_device(seq_file_net(seq)) : | ||
3102 | next_net_device((struct net_device *)v); | ||
3103 | |||
3101 | ++*pos; | 3104 | ++*pos; |
3102 | return v == SEQ_START_TOKEN ? | 3105 | return rcu_dereference(dev); |
3103 | first_net_device(net) : next_net_device((struct net_device *)v); | ||
3104 | } | 3106 | } |
3105 | 3107 | ||
3106 | void dev_seq_stop(struct seq_file *seq, void *v) | 3108 | void dev_seq_stop(struct seq_file *seq, void *v) |
3107 | __releases(dev_base_lock) | 3109 | __releases(RCU) |
3108 | { | 3110 | { |
3109 | read_unlock(&dev_base_lock); | 3111 | rcu_read_unlock(); |
3110 | } | 3112 | } |
3111 | 3113 | ||
3112 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) | 3114 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 664965c87e16..2e355841ca99 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -749,9 +749,9 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
749 | 749 | ||
750 | if (!(saddr->sdn_flags & SDF_WILD)) { | 750 | if (!(saddr->sdn_flags & SDF_WILD)) { |
751 | if (le16_to_cpu(saddr->sdn_nodeaddrl)) { | 751 | if (le16_to_cpu(saddr->sdn_nodeaddrl)) { |
752 | read_lock(&dev_base_lock); | 752 | rcu_read_lock(); |
753 | ldev = NULL; | 753 | ldev = NULL; |
754 | for_each_netdev(&init_net, dev) { | 754 | for_each_netdev_rcu(&init_net, dev) { |
755 | if (!dev->dn_ptr) | 755 | if (!dev->dn_ptr) |
756 | continue; | 756 | continue; |
757 | if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) { | 757 | if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) { |
@@ -759,7 +759,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
759 | break; | 759 | break; |
760 | } | 760 | } |
761 | } | 761 | } |
762 | read_unlock(&dev_base_lock); | 762 | rcu_read_unlock(); |
763 | if (ldev == NULL) | 763 | if (ldev == NULL) |
764 | return -EADDRNOTAVAIL; | 764 | return -EADDRNOTAVAIL; |
765 | } | 765 | } |
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index 27ea2e9b080a..fd641f65e092 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c | |||
@@ -607,8 +607,8 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa) | |||
607 | ASSERT_RTNL(); | 607 | ASSERT_RTNL(); |
608 | 608 | ||
609 | /* Scan device list */ | 609 | /* Scan device list */ |
610 | read_lock(&dev_base_lock); | 610 | rcu_read_lock(); |
611 | for_each_netdev(&init_net, dev) { | 611 | for_each_netdev_rcu(&init_net, dev) { |
612 | dn_db = dev->dn_ptr; | 612 | dn_db = dev->dn_ptr; |
613 | if (dn_db == NULL) | 613 | if (dn_db == NULL) |
614 | continue; | 614 | continue; |
@@ -619,7 +619,7 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa) | |||
619 | } | 619 | } |
620 | } | 620 | } |
621 | } | 621 | } |
622 | read_unlock(&dev_base_lock); | 622 | rcu_read_unlock(); |
623 | 623 | ||
624 | if (found_it == 0) { | 624 | if (found_it == 0) { |
625 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa); | 625 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa); |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 57662cabaf9b..860286a3921b 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -908,8 +908,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old | |||
908 | dev_put(dev_out); | 908 | dev_put(dev_out); |
909 | goto out; | 909 | goto out; |
910 | } | 910 | } |
911 | read_lock(&dev_base_lock); | 911 | rcu_read_lock(); |
912 | for_each_netdev(&init_net, dev) { | 912 | for_each_netdev_rcu(&init_net, dev) { |
913 | if (!dev->dn_ptr) | 913 | if (!dev->dn_ptr) |
914 | continue; | 914 | continue; |
915 | if (!dn_dev_islocal(dev, oldflp->fld_src)) | 915 | if (!dn_dev_islocal(dev, oldflp->fld_src)) |
@@ -922,7 +922,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old | |||
922 | dev_out = dev; | 922 | dev_out = dev; |
923 | break; | 923 | break; |
924 | } | 924 | } |
925 | read_unlock(&dev_base_lock); | 925 | rcu_read_unlock(); |
926 | if (dev_out == NULL) | 926 | if (dev_out == NULL) |
927 | goto out; | 927 | goto out; |
928 | dev_hold(dev_out); | 928 | dev_hold(dev_out); |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index ccccaae50b20..8aa7a134c1f1 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -876,19 +876,16 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) | |||
876 | if (!addr) | 876 | if (!addr) |
877 | addr = ifa->ifa_local; | 877 | addr = ifa->ifa_local; |
878 | } endfor_ifa(in_dev); | 878 | } endfor_ifa(in_dev); |
879 | no_in_dev: | ||
880 | rcu_read_unlock(); | ||
881 | 879 | ||
880 | no_in_dev: | ||
882 | if (addr) | 881 | if (addr) |
883 | goto out; | 882 | goto out_unlock; |
884 | 883 | ||
885 | /* Not loopback addresses on loopback should be preferred | 884 | /* Not loopback addresses on loopback should be preferred |
886 | in this case. It is importnat that lo is the first interface | 885 | in this case. It is importnat that lo is the first interface |
887 | in dev_base list. | 886 | in dev_base list. |
888 | */ | 887 | */ |
889 | read_lock(&dev_base_lock); | 888 | for_each_netdev_rcu(net, dev) { |
890 | rcu_read_lock(); | ||
891 | for_each_netdev(net, dev) { | ||
892 | if ((in_dev = __in_dev_get_rcu(dev)) == NULL) | 889 | if ((in_dev = __in_dev_get_rcu(dev)) == NULL) |
893 | continue; | 890 | continue; |
894 | 891 | ||
@@ -896,12 +893,11 @@ no_in_dev: | |||
896 | if (ifa->ifa_scope != RT_SCOPE_LINK && | 893 | if (ifa->ifa_scope != RT_SCOPE_LINK && |
897 | ifa->ifa_scope <= scope) { | 894 | ifa->ifa_scope <= scope) { |
898 | addr = ifa->ifa_local; | 895 | addr = ifa->ifa_local; |
899 | goto out_unlock_both; | 896 | goto out_unlock; |
900 | } | 897 | } |
901 | } endfor_ifa(in_dev); | 898 | } endfor_ifa(in_dev); |
902 | } | 899 | } |
903 | out_unlock_both: | 900 | out_unlock: |
904 | read_unlock(&dev_base_lock); | ||
905 | rcu_read_unlock(); | 901 | rcu_read_unlock(); |
906 | out: | 902 | out: |
907 | return addr; | 903 | return addr; |
@@ -962,9 +958,8 @@ __be32 inet_confirm_addr(struct in_device *in_dev, | |||
962 | return confirm_addr_indev(in_dev, dst, local, scope); | 958 | return confirm_addr_indev(in_dev, dst, local, scope); |
963 | 959 | ||
964 | net = dev_net(in_dev->dev); | 960 | net = dev_net(in_dev->dev); |
965 | read_lock(&dev_base_lock); | ||
966 | rcu_read_lock(); | 961 | rcu_read_lock(); |
967 | for_each_netdev(net, dev) { | 962 | for_each_netdev_rcu(net, dev) { |
968 | if ((in_dev = __in_dev_get_rcu(dev))) { | 963 | if ((in_dev = __in_dev_get_rcu(dev))) { |
969 | addr = confirm_addr_indev(in_dev, dst, local, scope); | 964 | addr = confirm_addr_indev(in_dev, dst, local, scope); |
970 | if (addr) | 965 | if (addr) |
@@ -972,7 +967,6 @@ __be32 inet_confirm_addr(struct in_device *in_dev, | |||
972 | } | 967 | } |
973 | } | 968 | } |
974 | rcu_read_unlock(); | 969 | rcu_read_unlock(); |
975 | read_unlock(&dev_base_lock); | ||
976 | 970 | ||
977 | return addr; | 971 | return addr; |
978 | } | 972 | } |
@@ -1240,18 +1234,18 @@ static void devinet_copy_dflt_conf(struct net *net, int i) | |||
1240 | { | 1234 | { |
1241 | struct net_device *dev; | 1235 | struct net_device *dev; |
1242 | 1236 | ||
1243 | read_lock(&dev_base_lock); | 1237 | rcu_read_lock(); |
1244 | for_each_netdev(net, dev) { | 1238 | for_each_netdev_rcu(net, dev) { |
1245 | struct in_device *in_dev; | 1239 | struct in_device *in_dev; |
1246 | rcu_read_lock(); | 1240 | |
1247 | in_dev = __in_dev_get_rcu(dev); | 1241 | in_dev = __in_dev_get_rcu(dev); |
1248 | if (in_dev && !test_bit(i, in_dev->cnf.state)) | 1242 | if (in_dev && !test_bit(i, in_dev->cnf.state)) |
1249 | in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i]; | 1243 | in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i]; |
1250 | rcu_read_unlock(); | ||
1251 | } | 1244 | } |
1252 | read_unlock(&dev_base_lock); | 1245 | rcu_read_unlock(); |
1253 | } | 1246 | } |
1254 | 1247 | ||
1248 | /* called with RTNL locked */ | ||
1255 | static void inet_forward_change(struct net *net) | 1249 | static void inet_forward_change(struct net *net) |
1256 | { | 1250 | { |
1257 | struct net_device *dev; | 1251 | struct net_device *dev; |
@@ -1260,7 +1254,6 @@ static void inet_forward_change(struct net *net) | |||
1260 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; | 1254 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; |
1261 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; | 1255 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; |
1262 | 1256 | ||
1263 | read_lock(&dev_base_lock); | ||
1264 | for_each_netdev(net, dev) { | 1257 | for_each_netdev(net, dev) { |
1265 | struct in_device *in_dev; | 1258 | struct in_device *in_dev; |
1266 | if (on) | 1259 | if (on) |
@@ -1271,7 +1264,6 @@ static void inet_forward_change(struct net *net) | |||
1271 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); | 1264 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); |
1272 | rcu_read_unlock(); | 1265 | rcu_read_unlock(); |
1273 | } | 1266 | } |
1274 | read_unlock(&dev_base_lock); | ||
1275 | } | 1267 | } |
1276 | 1268 | ||
1277 | static int devinet_conf_proc(ctl_table *ctl, int write, | 1269 | static int devinet_conf_proc(ctl_table *ctl, int write, |
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 | ||
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 4eb1ac9a7679..aacba76070fc 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c | |||
@@ -597,15 +597,15 @@ struct net_device *nr_dev_first(void) | |||
597 | { | 597 | { |
598 | struct net_device *dev, *first = NULL; | 598 | struct net_device *dev, *first = NULL; |
599 | 599 | ||
600 | read_lock(&dev_base_lock); | 600 | rcu_read_lock(); |
601 | for_each_netdev(&init_net, dev) { | 601 | for_each_netdev_rcu(&init_net, dev) { |
602 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM) | 602 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM) |
603 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) | 603 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) |
604 | first = dev; | 604 | first = dev; |
605 | } | 605 | } |
606 | if (first) | 606 | if (first) |
607 | dev_hold(first); | 607 | dev_hold(first); |
608 | read_unlock(&dev_base_lock); | 608 | rcu_read_unlock(); |
609 | 609 | ||
610 | return first; | 610 | return first; |
611 | } | 611 | } |
@@ -617,16 +617,17 @@ struct net_device *nr_dev_get(ax25_address *addr) | |||
617 | { | 617 | { |
618 | struct net_device *dev; | 618 | struct net_device *dev; |
619 | 619 | ||
620 | read_lock(&dev_base_lock); | 620 | rcu_read_lock(); |
621 | for_each_netdev(&init_net, dev) { | 621 | for_each_netdev_rcu(&init_net, dev) { |
622 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) { | 622 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && |
623 | ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) { | ||
623 | dev_hold(dev); | 624 | dev_hold(dev); |
624 | goto out; | 625 | goto out; |
625 | } | 626 | } |
626 | } | 627 | } |
627 | dev = NULL; | 628 | dev = NULL; |
628 | out: | 629 | out: |
629 | read_unlock(&dev_base_lock); | 630 | rcu_read_unlock(); |
630 | return dev; | 631 | return dev; |
631 | } | 632 | } |
632 | 633 | ||
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 9478d9b3d977..d936226916f2 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -600,13 +600,13 @@ struct net_device *rose_dev_first(void) | |||
600 | { | 600 | { |
601 | struct net_device *dev, *first = NULL; | 601 | struct net_device *dev, *first = NULL; |
602 | 602 | ||
603 | read_lock(&dev_base_lock); | 603 | rcu_read_lock(); |
604 | for_each_netdev(&init_net, dev) { | 604 | for_each_netdev_rcu(&init_net, dev) { |
605 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE) | 605 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE) |
606 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) | 606 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) |
607 | first = dev; | 607 | first = dev; |
608 | } | 608 | } |
609 | read_unlock(&dev_base_lock); | 609 | rcu_read_unlock(); |
610 | 610 | ||
611 | return first; | 611 | return first; |
612 | } | 612 | } |
@@ -618,8 +618,8 @@ struct net_device *rose_dev_get(rose_address *addr) | |||
618 | { | 618 | { |
619 | struct net_device *dev; | 619 | struct net_device *dev; |
620 | 620 | ||
621 | read_lock(&dev_base_lock); | 621 | rcu_read_lock(); |
622 | for_each_netdev(&init_net, dev) { | 622 | for_each_netdev_rcu(&init_net, dev) { |
623 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) { | 623 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) { |
624 | dev_hold(dev); | 624 | dev_hold(dev); |
625 | goto out; | 625 | goto out; |
@@ -627,7 +627,7 @@ struct net_device *rose_dev_get(rose_address *addr) | |||
627 | } | 627 | } |
628 | dev = NULL; | 628 | dev = NULL; |
629 | out: | 629 | out: |
630 | read_unlock(&dev_base_lock); | 630 | rcu_read_unlock(); |
631 | return dev; | 631 | return dev; |
632 | } | 632 | } |
633 | 633 | ||
@@ -635,14 +635,14 @@ static int rose_dev_exists(rose_address *addr) | |||
635 | { | 635 | { |
636 | struct net_device *dev; | 636 | struct net_device *dev; |
637 | 637 | ||
638 | read_lock(&dev_base_lock); | 638 | rcu_read_lock(); |
639 | for_each_netdev(&init_net, dev) { | 639 | for_each_netdev_rcu(&init_net, dev) { |
640 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) | 640 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) |
641 | goto out; | 641 | goto out; |
642 | } | 642 | } |
643 | dev = NULL; | 643 | dev = NULL; |
644 | out: | 644 | out: |
645 | read_unlock(&dev_base_lock); | 645 | rcu_read_unlock(); |
646 | return dev != NULL; | 646 | return dev != NULL; |
647 | } | 647 | } |
648 | 648 | ||
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d9f4cc2c7869..fe44c57101de 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -205,14 +205,14 @@ static void sctp_get_local_addr_list(void) | |||
205 | struct list_head *pos; | 205 | struct list_head *pos; |
206 | struct sctp_af *af; | 206 | struct sctp_af *af; |
207 | 207 | ||
208 | read_lock(&dev_base_lock); | 208 | rcu_read_lock(); |
209 | for_each_netdev(&init_net, dev) { | 209 | for_each_netdev_rcu(&init_net, dev) { |
210 | __list_for_each(pos, &sctp_address_families) { | 210 | __list_for_each(pos, &sctp_address_families) { |
211 | af = list_entry(pos, struct sctp_af, list); | 211 | af = list_entry(pos, struct sctp_af, list); |
212 | af->copy_addrlist(&sctp_local_addr_list, dev); | 212 | af->copy_addrlist(&sctp_local_addr_list, dev); |
213 | } | 213 | } |
214 | } | 214 | } |
215 | read_unlock(&dev_base_lock); | 215 | rcu_read_unlock(); |
216 | } | 216 | } |
217 | 217 | ||
218 | /* Free the existing local addresses. */ | 218 | /* Free the existing local addresses. */ |