Commit 54f13d39 authored by Dipankar Sarma's avatar Dipankar Sarma Committed by Hideaki Yoshifuji

[IPV4]: barriers in lockfree rtcache.

1. All the memory barriers are SMP-only avoiding unnecessary overhead on UP.
2, My forward porting merge of the rt_rcu patch dropped two changes in
   rt_intern_hash() in around 2.5.43 that ordered the writes while
   inserting a dst entry at the start of a hash chain. The dst entry updates
   must be visible to other (weakly ordered) CPUs before it is inserted.
   The necessary smp_wmb()s are added.
3. Comments to go with the write ordering.
parent fb2c0b11
...@@ -234,7 +234,7 @@ static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r) ...@@ -234,7 +234,7 @@ static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r)
{ {
struct rt_cache_iter_state *st = seq->private; struct rt_cache_iter_state *st = seq->private;
read_barrier_depends(); smp_read_barrier_depends();
r = r->u.rt_next; r = r->u.rt_next;
while (!r) { while (!r) {
rcu_read_unlock(); rcu_read_unlock();
...@@ -718,7 +718,18 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp) ...@@ -718,7 +718,18 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
if (compare_keys(&rth->fl, &rt->fl)) { if (compare_keys(&rth->fl, &rt->fl)) {
/* Put it first */ /* Put it first */
*rthp = rth->u.rt_next; *rthp = rth->u.rt_next;
/*
* Since lookup is lockfree, the deletion
* must be visible to another weakly ordered CPU before
* the insertion at the start of the hash chain.
*/
smp_wmb();
rth->u.rt_next = rt_hash_table[hash].chain; rth->u.rt_next = rt_hash_table[hash].chain;
/*
* Since lookup is lockfree, the update writes
* must be ordered for consistency on SMP.
*/
smp_wmb();
rt_hash_table[hash].chain = rth; rt_hash_table[hash].chain = rth;
rth->u.dst.__use++; rth->u.dst.__use++;
...@@ -900,7 +911,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, ...@@ -900,7 +911,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
while ((rth = *rthp) != NULL) { while ((rth = *rthp) != NULL) {
struct rtable *rt; struct rtable *rt;
read_barrier_depends(); smp_read_barrier_depends();
if (rth->fl.fl4_dst != daddr || if (rth->fl.fl4_dst != daddr ||
rth->fl.fl4_src != skeys[i] || rth->fl.fl4_src != skeys[i] ||
rth->fl.fl4_tos != tos || rth->fl.fl4_tos != tos ||
...@@ -1148,7 +1159,7 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu) ...@@ -1148,7 +1159,7 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
rcu_read_lock(); rcu_read_lock();
for (rth = rt_hash_table[hash].chain; rth; for (rth = rt_hash_table[hash].chain; rth;
rth = rth->u.rt_next) { rth = rth->u.rt_next) {
read_barrier_depends(); smp_read_barrier_depends();
if (rth->fl.fl4_dst == daddr && if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == skeys[i] && rth->fl.fl4_src == skeys[i] &&
rth->rt_dst == daddr && rth->rt_dst == daddr &&
...@@ -1740,7 +1751,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr, ...@@ -1740,7 +1751,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
rcu_read_lock(); rcu_read_lock();
for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) { for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
read_barrier_depends(); smp_read_barrier_depends();
if (rth->fl.fl4_dst == daddr && if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == saddr && rth->fl.fl4_src == saddr &&
rth->fl.iif == iif && rth->fl.iif == iif &&
...@@ -2105,7 +2116,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp) ...@@ -2105,7 +2116,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
rcu_read_lock(); rcu_read_lock();
for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) { for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
read_barrier_depends(); smp_read_barrier_depends();
if (rth->fl.fl4_dst == flp->fl4_dst && if (rth->fl.fl4_dst == flp->fl4_dst &&
rth->fl.fl4_src == flp->fl4_src && rth->fl.fl4_src == flp->fl4_src &&
rth->fl.iif == 0 && rth->fl.iif == 0 &&
...@@ -2335,7 +2346,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2335,7 +2346,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock(); rcu_read_lock();
for (rt = rt_hash_table[h].chain, idx = 0; rt; for (rt = rt_hash_table[h].chain, idx = 0; rt;
rt = rt->u.rt_next, idx++) { rt = rt->u.rt_next, idx++) {
read_barrier_depends(); smp_read_barrier_depends();
if (idx < s_idx) if (idx < s_idx)
continue; continue;
skb->dst = dst_clone(&rt->u.dst); skb->dst = dst_clone(&rt->u.dst);
......
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