ndisc: Update neigh->updated with write lock.
authorYOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>
Thu, 17 Jan 2013 12:53:02 +0000 (12:53 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 17 Jan 2013 23:38:18 +0000 (18:38 -0500)
neigh->nud_state and neigh->updated are under protection of
neigh->lock.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/route.c

index 7c34c01b515b7ac370f8021ba6f5ec4c654e9e41..1341f68e8009dc86b335c3baad51dec3d1189ced 100644 (file)
@@ -499,22 +499,26 @@ static void rt6_probe(struct rt6_info *rt)
         * to no more than one per minute.
         */
        neigh = rt ? rt->n : NULL;
-       if (!neigh || (neigh->nud_state & NUD_VALID))
+       if (!neigh)
+               return;
+       write_lock_bh(&neigh->lock);
+       if (neigh->nud_state & NUD_VALID) {
+               write_unlock_bh(&neigh->lock);
                return;
-       read_lock_bh(&neigh->lock);
+       }
        if (!(neigh->nud_state & NUD_VALID) &&
            time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
                struct in6_addr mcaddr;
                struct in6_addr *target;
 
                neigh->updated = jiffies;
-               read_unlock_bh(&neigh->lock);
+               write_unlock_bh(&neigh->lock);
 
                target = (struct in6_addr *)&neigh->primary_key;
                addrconf_addr_solict_mult(target, &mcaddr);
                ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL);
        } else {
-               read_unlock_bh(&neigh->lock);
+               write_unlock_bh(&neigh->lock);
        }
 }
 #else