diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-06-22 07:43:15 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-26 04:33:16 (GMT) |
commit | 4b4194c40f4ac8d03a700845f8978cba53246b5a (patch) | |
tree | 11beaa1417395708bc6af1d9fcc1da401b9bc1d6 /net/ipv4/arp.c | |
parent | 59b80802a8a18b64d38b51aa168253684b2649d5 (diff) | |
download | linux-4b4194c40f4ac8d03a700845f8978cba53246b5a.tar.xz |
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.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index cf78f41..09ead1b 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); |