Skip to content

Commit 70d2db7

Browse files
committed
Merge branch 'rt6_probe_write_lock'
Martin KaFai Lau says: ==================== ipv6: Avoid rt6_probe() taking writer lock in the fast path v1 -> v2: 1. Separate the code re-arrangement into another patch 2. Fix style ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 205845a + 8d6c31b commit 70d2db7

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

net/ipv6/route.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ static void rt6_probe_deferred(struct work_struct *w)
545545

546546
static void rt6_probe(struct rt6_info *rt)
547547
{
548+
struct __rt6_probe_work *work;
548549
struct neighbour *neigh;
549550
/*
550551
* Okay, this does not seem to be appropriate
@@ -559,34 +560,33 @@ static void rt6_probe(struct rt6_info *rt)
559560
rcu_read_lock_bh();
560561
neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
561562
if (neigh) {
562-
write_lock(&neigh->lock);
563563
if (neigh->nud_state & NUD_VALID)
564564
goto out;
565-
}
566-
567-
if (!neigh ||
568-
time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
569-
struct __rt6_probe_work *work;
570565

566+
work = NULL;
567+
write_lock(&neigh->lock);
568+
if (!(neigh->nud_state & NUD_VALID) &&
569+
time_after(jiffies,
570+
neigh->updated +
571+
rt->rt6i_idev->cnf.rtr_probe_interval)) {
572+
work = kmalloc(sizeof(*work), GFP_ATOMIC);
573+
if (work)
574+
__neigh_set_probe_once(neigh);
575+
}
576+
write_unlock(&neigh->lock);
577+
} else {
571578
work = kmalloc(sizeof(*work), GFP_ATOMIC);
579+
}
572580

573-
if (neigh && work)
574-
__neigh_set_probe_once(neigh);
575-
576-
if (neigh)
577-
write_unlock(&neigh->lock);
581+
if (work) {
582+
INIT_WORK(&work->work, rt6_probe_deferred);
583+
work->target = rt->rt6i_gateway;
584+
dev_hold(rt->dst.dev);
585+
work->dev = rt->dst.dev;
586+
schedule_work(&work->work);
587+
}
578588

579-
if (work) {
580-
INIT_WORK(&work->work, rt6_probe_deferred);
581-
work->target = rt->rt6i_gateway;
582-
dev_hold(rt->dst.dev);
583-
work->dev = rt->dst.dev;
584-
schedule_work(&work->work);
585-
}
586-
} else {
587589
out:
588-
write_unlock(&neigh->lock);
589-
}
590590
rcu_read_unlock_bh();
591591
}
592592
#else

0 commit comments

Comments
 (0)