|
@@ -545,6 +545,7 @@ static void rt6_probe_deferred(struct work_struct *w)
|
|
|
|
|
|
static void rt6_probe(struct rt6_info *rt)
|
|
|
{
|
|
|
+ struct __rt6_probe_work *work;
|
|
|
struct neighbour *neigh;
|
|
|
/*
|
|
|
* Okay, this does not seem to be appropriate
|
|
@@ -559,34 +560,29 @@ static void rt6_probe(struct rt6_info *rt)
|
|
|
rcu_read_lock_bh();
|
|
|
neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
|
|
|
if (neigh) {
|
|
|
+ work = NULL;
|
|
|
write_lock(&neigh->lock);
|
|
|
- if (neigh->nud_state & NUD_VALID)
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- if (!neigh ||
|
|
|
- time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
|
|
|
- struct __rt6_probe_work *work;
|
|
|
-
|
|
|
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
|
|
|
-
|
|
|
- if (neigh && work)
|
|
|
- __neigh_set_probe_once(neigh);
|
|
|
-
|
|
|
- if (neigh)
|
|
|
- write_unlock(&neigh->lock);
|
|
|
-
|
|
|
- if (work) {
|
|
|
- INIT_WORK(&work->work, rt6_probe_deferred);
|
|
|
- work->target = rt->rt6i_gateway;
|
|
|
- dev_hold(rt->dst.dev);
|
|
|
- work->dev = rt->dst.dev;
|
|
|
- schedule_work(&work->work);
|
|
|
+ if (!(neigh->nud_state & NUD_VALID) &&
|
|
|
+ time_after(jiffies,
|
|
|
+ neigh->updated +
|
|
|
+ rt->rt6i_idev->cnf.rtr_probe_interval)) {
|
|
|
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
|
|
|
+ if (work)
|
|
|
+ __neigh_set_probe_once(neigh);
|
|
|
}
|
|
|
- } else {
|
|
|
-out:
|
|
|
write_unlock(&neigh->lock);
|
|
|
+ } else {
|
|
|
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (work) {
|
|
|
+ INIT_WORK(&work->work, rt6_probe_deferred);
|
|
|
+ work->target = rt->rt6i_gateway;
|
|
|
+ dev_hold(rt->dst.dev);
|
|
|
+ work->dev = rt->dst.dev;
|
|
|
+ schedule_work(&work->work);
|
|
|
}
|
|
|
+
|
|
|
rcu_read_unlock_bh();
|
|
|
}
|
|
|
#else
|