aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip_fib.h2
-rw-r--r--net/ipv4/fib_semantics.c8
-rw-r--r--net/ipv4/route.c6
3 files changed, 9 insertions, 7 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 9922093f575e..f30fd554127e 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -87,7 +87,7 @@ struct fib_nh {
87 int nh_saddr_genid; 87 int nh_saddr_genid;
88 struct rtable __rcu * __percpu *nh_pcpu_rth_output; 88 struct rtable __rcu * __percpu *nh_pcpu_rth_output;
89 struct rtable __rcu *nh_rth_input; 89 struct rtable __rcu *nh_rth_input;
90 struct fnhe_hash_bucket *nh_exceptions; 90 struct fnhe_hash_bucket __rcu *nh_exceptions;
91}; 91};
92 92
93/* 93/*
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index b10cd43a4722..5b6efb3d2308 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -157,9 +157,12 @@ static void rt_fibinfo_free(struct rtable __rcu **rtp)
157 157
158static void free_nh_exceptions(struct fib_nh *nh) 158static void free_nh_exceptions(struct fib_nh *nh)
159{ 159{
160 struct fnhe_hash_bucket *hash = nh->nh_exceptions; 160 struct fnhe_hash_bucket *hash;
161 int i; 161 int i;
162 162
163 hash = rcu_dereference_protected(nh->nh_exceptions, 1);
164 if (!hash)
165 return;
163 for (i = 0; i < FNHE_HASH_SIZE; i++) { 166 for (i = 0; i < FNHE_HASH_SIZE; i++) {
164 struct fib_nh_exception *fnhe; 167 struct fib_nh_exception *fnhe;
165 168
@@ -205,8 +208,7 @@ static void free_fib_info_rcu(struct rcu_head *head)
205 change_nexthops(fi) { 208 change_nexthops(fi) {
206 if (nexthop_nh->nh_dev) 209 if (nexthop_nh->nh_dev)
207 dev_put(nexthop_nh->nh_dev); 210 dev_put(nexthop_nh->nh_dev);
208 if (nexthop_nh->nh_exceptions) 211 free_nh_exceptions(nexthop_nh);
209 free_nh_exceptions(nexthop_nh);
210 rt_fibinfo_free_cpus(nexthop_nh->nh_pcpu_rth_output); 212 rt_fibinfo_free_cpus(nexthop_nh->nh_pcpu_rth_output);
211 rt_fibinfo_free(&nexthop_nh->nh_rth_input); 213 rt_fibinfo_free(&nexthop_nh->nh_rth_input);
212 } endfor_nexthops(fi); 214 } endfor_nexthops(fi);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index eaa4b000c7b4..44b0cbdd76f1 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -628,12 +628,12 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
628 628
629 spin_lock_bh(&fnhe_lock); 629 spin_lock_bh(&fnhe_lock);
630 630
631 hash = nh->nh_exceptions; 631 hash = rcu_dereference(nh->nh_exceptions);
632 if (!hash) { 632 if (!hash) {
633 hash = kzalloc(FNHE_HASH_SIZE * sizeof(*hash), GFP_ATOMIC); 633 hash = kzalloc(FNHE_HASH_SIZE * sizeof(*hash), GFP_ATOMIC);
634 if (!hash) 634 if (!hash)
635 goto out_unlock; 635 goto out_unlock;
636 nh->nh_exceptions = hash; 636 rcu_assign_pointer(nh->nh_exceptions, hash);
637 } 637 }
638 638
639 hash += hval; 639 hash += hval;
@@ -1242,7 +1242,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
1242 1242
1243static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr) 1243static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr)
1244{ 1244{
1245 struct fnhe_hash_bucket *hash = nh->nh_exceptions; 1245 struct fnhe_hash_bucket *hash = rcu_dereference(nh->nh_exceptions);
1246 struct fib_nh_exception *fnhe; 1246 struct fib_nh_exception *fnhe;
1247 u32 hval; 1247 u32 hval;
1248 1248