Commit c5cff8561d2d adds rcu grace period before freeing fib6_node. This generates a new sparse warning on rt->rt6i_node related code: net/ipv6/route.c:1394:30: error: incompatible types in comparison expression (different address spaces) ./include/net/ip6_fib.h:187:14: error: incompatible types in comparison expression (different address spaces) This commit adds "__rcu" tag for rt6i_node and makes sure corresponding rcu API is used for it. After this fix, sparse no longer generates the above warning.
Unified · Split
| @@ -105,7 +105,7 @@ struct rt6_info { · 104 unmodified lines | |||
| 105 | * the same cache line. | 105 | * the same cache line. |
| 106 | */ | 106 | */ |
| 107 | struct fib6_table *rt6i_table; | 107 | struct fib6_table *rt6i_table; |
| 108 | struct fib6_node *rt6i_node; | 108 | struct fib6_node __rcu *rt6i_node; |
| 109 | 109 | ||
| 110 | struct in6_addr rt6i_gateway; | 110 | struct in6_addr rt6i_gateway; |
| 111 | 111 | ||
| @@ -5556,7 +5556,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) · 5555 unmodified lines | |||
| 5556 | * our DAD process, so we don't need | 5556 | * our DAD process, so we don't need |
| 5557 | * to do it again | 5557 | * to do it again |
| 5558 | */ | 5558 | */ |
| 5559 | if (!(ifp->rt->rt6i_node)) | 5559 | if (!rcu_access_pointer(ifp->rt->rt6i_node)) |
| 5560 | ip6_ins_rt(ifp->rt); | 5560 | ip6_ins_rt(ifp->rt); |
| 5561 | if (ifp->idev->cnf.forwarding) | 5561 | if (ifp->idev->cnf.forwarding) |
| 5562 | addrconf_join_anycast(ifp); | 5562 | addrconf_join_anycast(ifp); |
| @@ -889,7 +889,7 @@ add: · 888 unmodified lines | |||
| 889 | 889 | ||
| 890 | rt->dst.rt6_next = iter; | 890 | rt->dst.rt6_next = iter; |
| 891 | *ins = rt; | 891 | *ins = rt; |
| 892 | rt->rt6i_node = fn; | 892 | rcu_assign_pointer(rt->rt6i_node, fn); |
| 893 | atomic_inc(&rt->rt6i_ref); | 893 | atomic_inc(&rt->rt6i_ref); |
| 894 | if (!info->skip_notify) | 894 | if (!info->skip_notify) |
| 895 | inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags); | 895 | inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags); |
| @@ -915,7 +915,7 @@ add: · 19 unmodified lines | |||
| 915 | return err; | 915 | return err; |
| 916 | 916 | ||
| 917 | *ins = rt; | 917 | *ins = rt; |
| 918 | rt->rt6i_node = fn; | 918 | rcu_assign_pointer(rt->rt6i_node, fn); |
| 919 | rt->dst.rt6_next = iter->dst.rt6_next; | 919 | rt->dst.rt6_next = iter->dst.rt6_next; |
| 920 | atomic_inc(&rt->rt6i_ref); | 920 | atomic_inc(&rt->rt6i_ref); |
| 921 | if (!info->skip_notify) | 921 | if (!info->skip_notify) |
| @@ -1480,8 +1480,9 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, · 558 unmodified lines | |||
| 1480 | 1480 | ||
| 1481 | int fib6_del(struct rt6_info *rt, struct nl_info *info) | 1481 | int fib6_del(struct rt6_info *rt, struct nl_info *info) |
| 1482 | { | 1482 | { |
| 1483 | struct fib6_node *fn = rcu_dereference_protected(rt->rt6i_node, | ||
| 1484 | lockdep_is_held(&rt->rt6i_table->tb6_lock)); | ||
| 1483 | struct net *net = info->nl_net; | 1485 | struct net *net = info->nl_net; |
| 1484 | struct fib6_node *fn = rt->rt6i_node; | ||
| 1485 | struct rt6_info **rtp; | 1486 | struct rt6_info **rtp; |
| 1486 | 1487 | ||
| 1487 | #if RT6_DEBUG >= 2 | 1488 | #if RT6_DEBUG >= 2 |
| @@ -1670,7 +1671,9 @@ static int fib6_clean_node(struct fib6_walker *w) · 182 unmodified lines | |||
| 1670 | if (res) { | 1671 | if (res) { |
| 1671 | #if RT6_DEBUG >= 2 | 1672 | #if RT6_DEBUG >= 2 |
| 1672 | pr_debug("%s: del failed: rt=%p@%p err=%d\n", | 1673 | pr_debug("%s: del failed: rt=%p@%p err=%d\n", |
| 1673 | __func__, rt, rt->rt6i_node, res); | 1674 | __func__, rt, |
| 1675 | rcu_access_pointer(rt->rt6i_node), | ||
| 1676 | res); | ||
| 1674 | #endif | 1677 | #endif |
| 1675 | continue; | 1678 | continue; |
| 1676 | } | 1679 | } |
| @@ -1383,7 +1383,8 @@ static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu) · 1382 unmodified lines | |||
| 1383 | static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) | 1383 | static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) |
| 1384 | { | 1384 | { |
| 1385 | return !(rt->rt6i_flags & RTF_CACHE) && | 1385 | return !(rt->rt6i_flags & RTF_CACHE) && |
| 1386 | (rt->rt6i_flags & RTF_PCPU || rt->rt6i_node); | 1386 | (rt->rt6i_flags & RTF_PCPU || |
| 1387 | rcu_access_pointer(rt->rt6i_node)); | ||
| 1387 | } | 1388 | } |
| 1388 | 1389 | ||
| 1389 | static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, | 1390 | static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, |