aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2010-03-24 17:51:22 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-26 23:57:35 -0400
commit6a2bad70d546cf30a46bc6d9ec0cb9a0891a38eb (patch)
tree890e8db3cb7c5c8636b10e817b8cdbc5c90e265e /net
parentb35ecb5d404c00f2420221ccbb1bbba1139353a4 (diff)
ipv4: Restart rt_intern_hash after emergency rebuild (v2)
The the rebuild changes the genid which in turn is used at the hash calculation. Thus if we don't restart and go on with inserting the rt will happen in wrong chain. (Fixed Neil's comment about the index passed into the rt_intern_hash) Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Reviewed-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/route.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 124af1605d10..d413b57be9b3 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1097,7 +1097,7 @@ static int slow_chain_length(const struct rtable *head)
1097} 1097}
1098 1098
1099static int rt_intern_hash(unsigned hash, struct rtable *rt, 1099static int rt_intern_hash(unsigned hash, struct rtable *rt,
1100 struct rtable **rp, struct sk_buff *skb) 1100 struct rtable **rp, struct sk_buff *skb, int ifindex)
1101{ 1101{
1102 struct rtable *rth, **rthp; 1102 struct rtable *rth, **rthp;
1103 unsigned long now; 1103 unsigned long now;
@@ -1217,6 +1217,11 @@ restart:
1217 rt->u.dst.dev->name, num); 1217 rt->u.dst.dev->name, num);
1218 } 1218 }
1219 rt_emergency_hash_rebuild(net); 1219 rt_emergency_hash_rebuild(net);
1220 spin_unlock_bh(rt_hash_lock_addr(hash));
1221
1222 hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
1223 ifindex, rt_genid(net));
1224 goto restart;
1220 } 1225 }
1221 } 1226 }
1222 1227
@@ -1477,7 +1482,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1477 &netevent); 1482 &netevent);
1478 1483
1479 rt_del(hash, rth); 1484 rt_del(hash, rth);
1480 if (!rt_intern_hash(hash, rt, &rt, NULL)) 1485 if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))
1481 ip_rt_put(rt); 1486 ip_rt_put(rt);
1482 goto do_next; 1487 goto do_next;
1483 } 1488 }
@@ -1931,7 +1936,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1931 1936
1932 in_dev_put(in_dev); 1937 in_dev_put(in_dev);
1933 hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); 1938 hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
1934 return rt_intern_hash(hash, rth, NULL, skb); 1939 return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);
1935 1940
1936e_nobufs: 1941e_nobufs:
1937 in_dev_put(in_dev); 1942 in_dev_put(in_dev);
@@ -2098,7 +2103,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
2098 /* put it into the cache */ 2103 /* put it into the cache */
2099 hash = rt_hash(daddr, saddr, fl->iif, 2104 hash = rt_hash(daddr, saddr, fl->iif,
2100 rt_genid(dev_net(rth->u.dst.dev))); 2105 rt_genid(dev_net(rth->u.dst.dev)));
2101 return rt_intern_hash(hash, rth, NULL, skb); 2106 return rt_intern_hash(hash, rth, NULL, skb, fl->iif);
2102} 2107}
2103 2108
2104/* 2109/*
@@ -2255,7 +2260,7 @@ local_input:
2255 } 2260 }
2256 rth->rt_type = res.type; 2261 rth->rt_type = res.type;
2257 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); 2262 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
2258 err = rt_intern_hash(hash, rth, NULL, skb); 2263 err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
2259 goto done; 2264 goto done;
2260 2265
2261no_route: 2266no_route:
@@ -2502,7 +2507,7 @@ static int ip_mkroute_output(struct rtable **rp,
2502 if (err == 0) { 2507 if (err == 0) {
2503 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, 2508 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
2504 rt_genid(dev_net(dev_out))); 2509 rt_genid(dev_net(dev_out)));
2505 err = rt_intern_hash(hash, rth, rp, NULL); 2510 err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);
2506 } 2511 }
2507 2512
2508 return err; 2513 return err;