From a7d69f344766ba459e6293be86f4bf431551eb47 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 22 Jun 2009 10:18:53 +0000 Subject: [PATCH] --- yaml --- r: 154112 b: refs/heads/master c: b6280b47a7a42970d098a3059f4ebe7e55e90d8d h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/net/ipv4/route.c | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index cadc29505354..423bded576fe 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d55d87fdff8252d0e2f7c28c2d443aee17e9d70f +refs/heads/master: b6280b47a7a42970d098a3059f4ebe7e55e90d8d diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 65b3a8b11a6c..278f46f5011b 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -1093,8 +1093,27 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, * If we drop it here, the callers have no way to resolve routes * when we're not caching. Instead, just point *rp at rt, so * the caller gets a single use out of the route + * Note that we do rt_free on this new route entry, so that + * once its refcount hits zero, we are still able to reap it + * (Thanks Alexey) + * Note also the rt_free uses call_rcu. We don't actually + * need rcu protection here, this is just our path to get + * on the route gc list. */ - goto report_and_exit; + + if (rt->rt_type == RTN_UNICAST || rt->fl.iif == 0) { + int err = arp_bind_neighbour(&rt->u.dst); + if (err) { + if (net_ratelimit()) + printk(KERN_WARNING + "Neighbour table failure & not caching routes.\n"); + rt_drop(rt); + return err; + } + } + + rt_free(rt); + goto skip_hashing; } rthp = &rt_hash_table[hash].chain; @@ -1211,7 +1230,8 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, #if RT_CACHE_DEBUG >= 2 if (rt->u.dst.rt_next) { struct rtable *trt; - printk(KERN_DEBUG "rt_cache @%02x: %pI4", hash, &rt->rt_dst); + printk(KERN_DEBUG "rt_cache @%02x: %pI4", + hash, &rt->rt_dst); for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next) printk(" . %pI4", &trt->rt_dst); printk("\n"); @@ -1226,7 +1246,7 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, spin_unlock_bh(rt_hash_lock_addr(hash)); -report_and_exit: +skip_hashing: if (rp) *rp = rt; else