summaryrefslogtreecommitdiffstats
path: root/net/ipv4/arp.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-06-22 09:43:15 +0200
committerDavid S. Miller <davem@davemloft.net>2010-06-26 06:33:16 +0200
commit4b4194c40f4ac8d03a700845f8978cba53246b5a (patch)
tree11beaa1417395708bc6af1d9fcc1da401b9bc1d6 /net/ipv4/arp.c
parentdccp: make implementation of Syn-RTT symmetric (diff)
downloadlinux-4b4194c40f4ac8d03a700845f8978cba53246b5a.tar.xz
linux-4b4194c40f4ac8d03a700845f8978cba53246b5a.zip
arp: RCU change in arp_solicit()
Avoid two atomic ops in arp_solicit() Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r--net/ipv4/arp.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index cf78f41830ca..09ead1baa99e 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -333,11 +333,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
struct net_device *dev = neigh->dev;
__be32 target = *(__be32*)neigh->primary_key;
int probes = atomic_read(&neigh->probes);
- struct in_device *in_dev = in_dev_get(dev);
+ struct in_device *in_dev;
- if (!in_dev)
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
+ if (!in_dev) {
+ rcu_read_unlock();
return;
-
+ }
switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
default:
case 0: /* By default announce any local IP */
@@ -358,9 +361,8 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
case 2: /* Avoid secondary IPs, get a primary/preferred one */
break;
}
+ rcu_read_unlock();
- if (in_dev)
- in_dev_put(in_dev);
if (!saddr)
saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);