aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
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 /net/ipv4/devinet.c
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>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c30
1 files changed, 11 insertions, 19 deletions
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,