aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-06-08 00:49:44 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-08 00:49:44 -0400
commited7865a47d4759e85bbd7bed44bee411d868eaad (patch)
treef0d2bd7d1f6c2c9d962baf84d2041a5b8c1c6b64 /net/ipv4
parent9a57a9d291980302b4a3184fbc47dbddac71903e (diff)
ipv4: avoid two atomic ops in ip_rt_redirect()
in_dev_get() -> __in_dev_get_rcu() in a rcu protected function. [ Fix build with CONFIG_IP_ROUTE_VERBOSE disabled. -DaveM ] Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/route.c10
1 files changed, 3 insertions, 7 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 7b8eacd5ac26..883b5c7195ac 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1343,11 +1343,12 @@ static void rt_del(unsigned hash, struct rtable *rt)
1343 spin_unlock_bh(rt_hash_lock_addr(hash)); 1343 spin_unlock_bh(rt_hash_lock_addr(hash));
1344} 1344}
1345 1345
1346/* called in rcu_read_lock() section */
1346void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, 1347void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1347 __be32 saddr, struct net_device *dev) 1348 __be32 saddr, struct net_device *dev)
1348{ 1349{
1349 int i, k; 1350 int i, k;
1350 struct in_device *in_dev = in_dev_get(dev); 1351 struct in_device *in_dev = __in_dev_get_rcu(dev);
1351 struct rtable *rth, **rthp; 1352 struct rtable *rth, **rthp;
1352 __be32 skeys[2] = { saddr, 0 }; 1353 __be32 skeys[2] = { saddr, 0 };
1353 int ikeys[2] = { dev->ifindex, 0 }; 1354 int ikeys[2] = { dev->ifindex, 0 };
@@ -1383,7 +1384,6 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1383 1384
1384 rthp=&rt_hash_table[hash].chain; 1385 rthp=&rt_hash_table[hash].chain;
1385 1386
1386 rcu_read_lock();
1387 while ((rth = rcu_dereference(*rthp)) != NULL) { 1387 while ((rth = rcu_dereference(*rthp)) != NULL) {
1388 struct rtable *rt; 1388 struct rtable *rt;
1389 1389
@@ -1405,12 +1405,10 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1405 break; 1405 break;
1406 1406
1407 dst_hold(&rth->u.dst); 1407 dst_hold(&rth->u.dst);
1408 rcu_read_unlock();
1409 1408
1410 rt = dst_alloc(&ipv4_dst_ops); 1409 rt = dst_alloc(&ipv4_dst_ops);
1411 if (rt == NULL) { 1410 if (rt == NULL) {
1412 ip_rt_put(rth); 1411 ip_rt_put(rth);
1413 in_dev_put(in_dev);
1414 return; 1412 return;
1415 } 1413 }
1416 1414
@@ -1463,12 +1461,10 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1463 ip_rt_put(rt); 1461 ip_rt_put(rt);
1464 goto do_next; 1462 goto do_next;
1465 } 1463 }
1466 rcu_read_unlock();
1467 do_next: 1464 do_next:
1468 ; 1465 ;
1469 } 1466 }
1470 } 1467 }
1471 in_dev_put(in_dev);
1472 return; 1468 return;
1473 1469
1474reject_redirect: 1470reject_redirect:
@@ -1479,7 +1475,7 @@ reject_redirect:
1479 &old_gw, dev->name, &new_gw, 1475 &old_gw, dev->name, &new_gw,
1480 &saddr, &daddr); 1476 &saddr, &daddr);
1481#endif 1477#endif
1482 in_dev_put(in_dev); 1478 ;
1483} 1479}
1484 1480
1485static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) 1481static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)