Since udp_tunnel{,6}_dst_lookup return a dstref, we can avoid incrementing the refcount on the returned dst and return a noref dst. This only applies when CONFIG_DST_CACHE is enabled. Otherwise we always perform an output routing lookup, which returns an owned dst. Update udp_tunnel{,6}_dst_lookup to return a noref dst. Signed-off-by: Marek Mietus --- net/ipv4/udp_tunnel_core.c | 13 ++++++++----- net/ipv6/ip6_udp_tunnel.c | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c index fdfa5420f9bf..9859d6d5f521 100644 --- a/net/ipv4/udp_tunnel_core.c +++ b/net/ipv4/udp_tunnel_core.c @@ -240,9 +240,9 @@ int udp_tunnel_dst_lookup(struct sk_buff *skb, #ifdef CONFIG_DST_CACHE if (dst_cache) { - rt = dst_cache_get_ip4(dst_cache, saddr); + rt = dst_cache_get_ip4_rcu(dst_cache, saddr); if (rt) { - *dstref = dst_to_dstref(&rt->dst); + *dstref = dst_to_dstref_noref(&rt->dst); return 0; } } @@ -269,11 +269,14 @@ int udp_tunnel_dst_lookup(struct sk_buff *skb, ip_rt_put(rt); return -ELOOP; } + *saddr = fl4.saddr; #ifdef CONFIG_DST_CACHE - if (dst_cache) - dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr); + if (dst_cache) { + dst_cache_steal_ip4(dst_cache, &rt->dst, fl4.saddr); + *dstref = dst_to_dstref_noref(&rt->dst); + return 0; + } #endif - *saddr = fl4.saddr; *dstref = dst_to_dstref(&rt->dst); return 0; } diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c index ec7bf7d744fe..e832d08b643d 100644 --- a/net/ipv6/ip6_udp_tunnel.c +++ b/net/ipv6/ip6_udp_tunnel.c @@ -149,9 +149,9 @@ int udp_tunnel6_dst_lookup(struct sk_buff *skb, #ifdef CONFIG_DST_CACHE if (dst_cache) { - dst = dst_cache_get_ip6(dst_cache, saddr); + dst = dst_cache_get_ip6_rcu(dst_cache, saddr); if (dst) { - *dstref = dst_to_dstref(dst); + *dstref = dst_to_dstref_noref(dst); return 0; } } @@ -177,11 +177,14 @@ int udp_tunnel6_dst_lookup(struct sk_buff *skb, dst_release(dst); return -ELOOP; } + *saddr = fl6.saddr; #ifdef CONFIG_DST_CACHE - if (dst_cache) - dst_cache_set_ip6(dst_cache, dst, &fl6.saddr); + if (dst_cache) { + dst_cache_steal_ip6(dst_cache, dst, &fl6.saddr); + *dstref = dst_to_dstref_noref(dst); + return 0; + } #endif - *saddr = fl6.saddr; *dstref = dst_to_dstref(dst); return 0; } -- 2.51.0