arp: RCU change in arp_solicit()
authorEric Dumazet <eric.dumazet@gmail.com>
Tue, 22 Jun 2010 07:43:15 +0000 (07:43 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 26 Jun 2010 04:33:16 +0000 (21:33 -0700)
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>
net/ipv4/arp.c

index cf78f41830ca97d971d06b5fa30baef739382df0..09ead1baa99e87b806c3881af1d31841a3df4124 100644 (file)
@@ -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);