Commit 6a2bad70 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by David S. Miller

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: default avatarPavel Emelyanov <xemul@openvz.org>
Reviewed-by: default avatarNeil Horman <nhorman@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b35ecb5d
...@@ -1097,7 +1097,7 @@ static int slow_chain_length(const struct rtable *head) ...@@ -1097,7 +1097,7 @@ static int slow_chain_length(const struct rtable *head)
} }
static int rt_intern_hash(unsigned hash, struct rtable *rt, static int rt_intern_hash(unsigned hash, struct rtable *rt,
struct rtable **rp, struct sk_buff *skb) struct rtable **rp, struct sk_buff *skb, int ifindex)
{ {
struct rtable *rth, **rthp; struct rtable *rth, **rthp;
unsigned long now; unsigned long now;
...@@ -1217,6 +1217,11 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, ...@@ -1217,6 +1217,11 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt,
rt->u.dst.dev->name, num); rt->u.dst.dev->name, num);
} }
rt_emergency_hash_rebuild(net); rt_emergency_hash_rebuild(net);
spin_unlock_bh(rt_hash_lock_addr(hash));
hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
ifindex, rt_genid(net));
goto restart;
} }
} }
...@@ -1477,7 +1482,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, ...@@ -1477,7 +1482,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
&netevent); &netevent);
rt_del(hash, rth); rt_del(hash, rth);
if (!rt_intern_hash(hash, rt, &rt, NULL)) if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))
ip_rt_put(rt); ip_rt_put(rt);
goto do_next; goto do_next;
} }
...@@ -1931,7 +1936,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -1931,7 +1936,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
in_dev_put(in_dev); in_dev_put(in_dev);
hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
return rt_intern_hash(hash, rth, NULL, skb); return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);
e_nobufs: e_nobufs:
in_dev_put(in_dev); in_dev_put(in_dev);
...@@ -2098,7 +2103,7 @@ static int ip_mkroute_input(struct sk_buff *skb, ...@@ -2098,7 +2103,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
/* put it into the cache */ /* put it into the cache */
hash = rt_hash(daddr, saddr, fl->iif, hash = rt_hash(daddr, saddr, fl->iif,
rt_genid(dev_net(rth->u.dst.dev))); rt_genid(dev_net(rth->u.dst.dev)));
return rt_intern_hash(hash, rth, NULL, skb); return rt_intern_hash(hash, rth, NULL, skb, fl->iif);
} }
/* /*
...@@ -2255,7 +2260,7 @@ out: return err; ...@@ -2255,7 +2260,7 @@ out: return err;
} }
rth->rt_type = res.type; rth->rt_type = res.type;
hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
err = rt_intern_hash(hash, rth, NULL, skb); err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
goto done; goto done;
no_route: no_route:
...@@ -2502,7 +2507,7 @@ static int ip_mkroute_output(struct rtable **rp, ...@@ -2502,7 +2507,7 @@ static int ip_mkroute_output(struct rtable **rp,
if (err == 0) { if (err == 0) {
hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
rt_genid(dev_net(dev_out))); rt_genid(dev_net(dev_out)));
err = rt_intern_hash(hash, rth, rp, NULL); err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);
} }
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment