diff options
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cd76b3cb7092..278f46f5011b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1085,8 +1085,35 @@ restart: | |||
1085 | now = jiffies; | 1085 | now = jiffies; |
1086 | 1086 | ||
1087 | if (!rt_caching(dev_net(rt->u.dst.dev))) { | 1087 | if (!rt_caching(dev_net(rt->u.dst.dev))) { |
1088 | rt_drop(rt); | 1088 | /* |
1089 | return 0; | 1089 | * If we're not caching, just tell the caller we |
1090 | * were successful and don't touch the route. The | ||
1091 | * caller hold the sole reference to the cache entry, and | ||
1092 | * it will be released when the caller is done with it. | ||
1093 | * If we drop it here, the callers have no way to resolve routes | ||
1094 | * when we're not caching. Instead, just point *rp at rt, so | ||
1095 | * the caller gets a single use out of the route | ||
1096 | * Note that we do rt_free on this new route entry, so that | ||
1097 | * once its refcount hits zero, we are still able to reap it | ||
1098 | * (Thanks Alexey) | ||
1099 | * Note also the rt_free uses call_rcu. We don't actually | ||
1100 | * need rcu protection here, this is just our path to get | ||
1101 | * on the route gc list. | ||
1102 | */ | ||
1103 | |||
1104 | if (rt->rt_type == RTN_UNICAST || rt->fl.iif == 0) { | ||
1105 | int err = arp_bind_neighbour(&rt->u.dst); | ||
1106 | if (err) { | ||
1107 | if (net_ratelimit()) | ||
1108 | printk(KERN_WARNING | ||
1109 | "Neighbour table failure & not caching routes.\n"); | ||
1110 | rt_drop(rt); | ||
1111 | return err; | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | rt_free(rt); | ||
1116 | goto skip_hashing; | ||
1090 | } | 1117 | } |
1091 | 1118 | ||
1092 | rthp = &rt_hash_table[hash].chain; | 1119 | rthp = &rt_hash_table[hash].chain; |
@@ -1203,7 +1230,8 @@ restart: | |||
1203 | #if RT_CACHE_DEBUG >= 2 | 1230 | #if RT_CACHE_DEBUG >= 2 |
1204 | if (rt->u.dst.rt_next) { | 1231 | if (rt->u.dst.rt_next) { |
1205 | struct rtable *trt; | 1232 | struct rtable *trt; |
1206 | printk(KERN_DEBUG "rt_cache @%02x: %pI4", hash, &rt->rt_dst); | 1233 | printk(KERN_DEBUG "rt_cache @%02x: %pI4", |
1234 | hash, &rt->rt_dst); | ||
1207 | for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next) | 1235 | for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next) |
1208 | printk(" . %pI4", &trt->rt_dst); | 1236 | printk(" . %pI4", &trt->rt_dst); |
1209 | printk("\n"); | 1237 | printk("\n"); |
@@ -1217,6 +1245,8 @@ restart: | |||
1217 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); | 1245 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); |
1218 | 1246 | ||
1219 | spin_unlock_bh(rt_hash_lock_addr(hash)); | 1247 | spin_unlock_bh(rt_hash_lock_addr(hash)); |
1248 | |||
1249 | skip_hashing: | ||
1220 | if (rp) | 1250 | if (rp) |
1221 | *rp = rt; | 1251 | *rp = rt; |
1222 | else | 1252 | else |