aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-11-04 08:43:23 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-04 08:43:23 -0500
commitc6d14c84566d6b70ad9dc1618db0dec87cca9300 (patch)
tree5ec75245cfda4d61e6b4506b6217f047ff4af01a
parentd0075634cf9d288988f57392a1f132d2053af961 (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.h2
-rw-r--r--net/core/dev.c30
-rw-r--r--net/decnet/af_decnet.c6
-rw-r--r--net/decnet/dn_fib.c6
-rw-r--r--net/decnet/dn_route.c6
-rw-r--r--net/ipv4/devinet.c30
-rw-r--r--net/ipv6/addrconf.c20
-rw-r--r--net/ipv6/anycast.c6
-rw-r--r--net/netrom/nr_route.c15
-rw-r--r--net/rose/rose_route.c18
-rw-r--r--net/sctp/protocol.c6
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}
813EXPORT_SYMBOL(dev_get_by_flags); 813EXPORT_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 */
3079void *dev_seq_start(struct seq_file *seq, loff_t *pos) 3079void *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
3098void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 3098void *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
3106void dev_seq_stop(struct seq_file *seq, void *v) 3108void 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
3112static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) 3114static 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);
879no_in_dev:
880 rcu_read_unlock();
881 879
880no_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 }
903out_unlock_both: 900out_unlock:
904 read_unlock(&dev_base_lock);
905 rcu_read_unlock(); 901 rcu_read_unlock();
906out: 902out:
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 */
1255static void inet_forward_change(struct net *net) 1249static 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
1277static int devinet_conf_proc(ctl_table *ctl, int write, 1269static 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
499static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) 497static 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
4070static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) 4064static 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;
628out: 629out:
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;
629out: 629out:
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;
644out: 644out:
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. */