aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index da449ddb8cc1..ad9ad4aab5da 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -203,6 +203,7 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp)
203static void free_fib_info_rcu(struct rcu_head *head) 203static void free_fib_info_rcu(struct rcu_head *head)
204{ 204{
205 struct fib_info *fi = container_of(head, struct fib_info, rcu); 205 struct fib_info *fi = container_of(head, struct fib_info, rcu);
206 struct dst_metrics *m;
206 207
207 change_nexthops(fi) { 208 change_nexthops(fi) {
208 if (nexthop_nh->nh_dev) 209 if (nexthop_nh->nh_dev)
@@ -213,8 +214,9 @@ static void free_fib_info_rcu(struct rcu_head *head)
213 rt_fibinfo_free(&nexthop_nh->nh_rth_input); 214 rt_fibinfo_free(&nexthop_nh->nh_rth_input);
214 } endfor_nexthops(fi); 215 } endfor_nexthops(fi);
215 216
216 if (fi->fib_metrics != (u32 *) dst_default_metrics) 217 m = fi->fib_metrics;
217 kfree(fi->fib_metrics); 218 if (m != &dst_default_metrics && atomic_dec_and_test(&m->refcnt))
219 kfree(m);
218 kfree(fi); 220 kfree(fi);
219} 221}
220 222
@@ -971,11 +973,11 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg)
971 val = 255; 973 val = 255;
972 if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK)) 974 if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK))
973 return -EINVAL; 975 return -EINVAL;
974 fi->fib_metrics[type - 1] = val; 976 fi->fib_metrics->metrics[type - 1] = val;
975 } 977 }
976 978
977 if (ecn_ca) 979 if (ecn_ca)
978 fi->fib_metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA; 980 fi->fib_metrics->metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA;
979 981
980 return 0; 982 return 0;
981} 983}
@@ -1033,11 +1035,12 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
1033 goto failure; 1035 goto failure;
1034 fib_info_cnt++; 1036 fib_info_cnt++;
1035 if (cfg->fc_mx) { 1037 if (cfg->fc_mx) {
1036 fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); 1038 fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL);
1037 if (!fi->fib_metrics) 1039 if (!fi->fib_metrics)
1038 goto failure; 1040 goto failure;
1041 atomic_set(&fi->fib_metrics->refcnt, 1);
1039 } else 1042 } else
1040 fi->fib_metrics = (u32 *) dst_default_metrics; 1043 fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
1041 1044
1042 fi->fib_net = net; 1045 fi->fib_net = net;
1043 fi->fib_protocol = cfg->fc_protocol; 1046 fi->fib_protocol = cfg->fc_protocol;
@@ -1238,7 +1241,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
1238 if (fi->fib_priority && 1241 if (fi->fib_priority &&
1239 nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority)) 1242 nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority))
1240 goto nla_put_failure; 1243 goto nla_put_failure;
1241 if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) 1244 if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0)
1242 goto nla_put_failure; 1245 goto nla_put_failure;
1243 1246
1244 if (fi->fib_prefsrc && 1247 if (fi->fib_prefsrc &&