diff mbox series

[net-next,3/3] dst_cache: let rt_uncached cope with dst_cache cleanup

Message ID cd710487a34149654a5ff73a8c0df9b1d3fc73a9.1717087015.git.pabeni@redhat.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series dst_cache: cope with device removal | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 904 this patch: 906
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang fail Errors and warnings before: 906 this patch: 911
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn fail Errors and warnings before: 908 this patch: 910
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 32 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Paolo Abeni May 30, 2024, 5:21 p.m. UTC
Eric reported that dst_cache don't cope correctly with device removal,
keeping the cached dst unmodified even when the underlining device is
deleted and the dst itself is not uncached.

The above causes the infamous 'unregistering netdevice' hangup.

Address the issue by adding each entry held by the dst_caches to the
'uncached' list, so that the dst core will cleanup the device reference
at device removal time.

Reported-by: Eric Dumazet <edumazet@google.com>
Suggested-by: Eric Dumazet <edumazet@google.com>
Fixes: 911362c70df5 ("net: add dst_cache support")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/core/dst_cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Eric Dumazet May 30, 2024, 5:46 p.m. UTC | #1
On Thu, May 30, 2024 at 7:21 PM Paolo Abeni <pabeni@redhat.com> wrote:
>
> Eric reported that dst_cache don't cope correctly with device removal,
> keeping the cached dst unmodified even when the underlining device is
> deleted and the dst itself is not uncached.
>
> The above causes the infamous 'unregistering netdevice' hangup.
>
> Address the issue by adding each entry held by the dst_caches to the
> 'uncached' list, so that the dst core will cleanup the device reference
> at device removal time.
>
> Reported-by: Eric Dumazet <edumazet@google.com>
> Suggested-by: Eric Dumazet <edumazet@google.com>
> Fixes: 911362c70df5 ("net: add dst_cache support")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> ---
>  net/core/dst_cache.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/net/core/dst_cache.c b/net/core/dst_cache.c
> index 6a0482e676d3..d1cb852d5748 100644
> --- a/net/core/dst_cache.c
> +++ b/net/core/dst_cache.c
> @@ -11,6 +11,7 @@
>  #include <net/route.h>
>  #if IS_ENABLED(CONFIG_IPV6)
>  #include <net/ip6_fib.h>
> +#include <net/ip6_route.h>
>  #endif
>  #include <uapi/linux/in.h>
>
> @@ -28,6 +29,7 @@ static void dst_cache_per_cpu_dst_set(struct dst_cache_pcpu *dst_cache,
>                                       struct dst_entry *dst, u32 cookie)
>  {
>         dst_release(dst_cache->dst);
> +
>         if (dst)
>                 dst_hold(dst);
>
> @@ -98,6 +100,9 @@ void dst_cache_set_ip4(struct dst_cache *dst_cache, struct dst_entry *dst,
>
>         idst = this_cpu_ptr(dst_cache->cache);
>         dst_cache_per_cpu_dst_set(idst, dst, 0);
> +       if (dst && list_empty(&dst->rt_uncached))
> +               rt_add_uncached_list(dst_rtable(dst));
> +
>         idst->in_saddr.s_addr = saddr;
>  }
>  EXPORT_SYMBOL_GPL(dst_cache_set_ip4);
> @@ -114,6 +119,9 @@ void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst,
>         idst = this_cpu_ptr(dst_cache->cache);
>         dst_cache_per_cpu_dst_set(idst, dst,
>                                   rt6_get_cookie(dst_rt6_info(dst)));
> +       if (dst && list_empty(&dst->rt_uncached))
> +               rt6_uncached_list_add(dst_rt6_info(dst));

This probably will not compile if CONFIG_IPV6=m ?
kernel test robot May 31, 2024, 10:53 a.m. UTC | #2
Hi Paolo,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Paolo-Abeni/ipv6-use-a-new-flag-to-indicate-elevated-refcount/20240531-012716
base:   net-next/main
patch link:    https://lore.kernel.org/r/cd710487a34149654a5ff73a8c0df9b1d3fc73a9.1717087015.git.pabeni%40redhat.com
patch subject: [PATCH net-next 3/3] dst_cache: let rt_uncached cope with dst_cache cleanup
config: arm64-defconfig (https://download.01.org/0day-ci/archive/20240531/202405311808.vqBTwxEf-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240531/202405311808.vqBTwxEf-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405311808.vqBTwxEf-lkp@intel.com/

All errors (new ones prefixed by >>):

   aarch64-linux-ld: Unexpected GOT/PLT entries detected!
   aarch64-linux-ld: Unexpected run-time procedure linkages detected!
   aarch64-linux-ld: net/core/dst_cache.o: in function `dst_cache_set_ip6':
>> net/core/dst_cache.c:123:(.text+0x240): undefined reference to `rt6_uncached_list_add'


vim +123 net/core/dst_cache.c

   109	
   110	#if IS_ENABLED(CONFIG_IPV6)
   111	void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst,
   112			       const struct in6_addr *saddr)
   113	{
   114		struct dst_cache_pcpu *idst;
   115	
   116		if (!dst_cache->cache)
   117			return;
   118	
   119		idst = this_cpu_ptr(dst_cache->cache);
   120		dst_cache_per_cpu_dst_set(idst, dst,
   121					  rt6_get_cookie(dst_rt6_info(dst)));
   122		if (dst && list_empty(&dst->rt_uncached))
 > 123			rt6_uncached_list_add(dst_rt6_info(dst));
   124	
   125		idst->in6_saddr = *saddr;
   126	}
   127	EXPORT_SYMBOL_GPL(dst_cache_set_ip6);
   128
kernel test robot May 31, 2024, 5:32 p.m. UTC | #3
Hi Paolo,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Paolo-Abeni/ipv6-use-a-new-flag-to-indicate-elevated-refcount/20240531-012716
base:   net-next/main
patch link:    https://lore.kernel.org/r/cd710487a34149654a5ff73a8c0df9b1d3fc73a9.1717087015.git.pabeni%40redhat.com
patch subject: [PATCH net-next 3/3] dst_cache: let rt_uncached cope with dst_cache cleanup
config: m68k-defconfig (https://download.01.org/0day-ci/archive/20240601/202406010139.PSZGIJkQ-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240601/202406010139.PSZGIJkQ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202406010139.PSZGIJkQ-lkp@intel.com/

All errors (new ones prefixed by >>):

   m68k-linux-ld: net/core/dst_cache.o: in function `dst_cache_set_ip6':
>> dst_cache.c:(.text+0x21e): undefined reference to `rt6_uncached_list_add'
diff mbox series

Patch

diff --git a/net/core/dst_cache.c b/net/core/dst_cache.c
index 6a0482e676d3..d1cb852d5748 100644
--- a/net/core/dst_cache.c
+++ b/net/core/dst_cache.c
@@ -11,6 +11,7 @@ 
 #include <net/route.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ip6_fib.h>
+#include <net/ip6_route.h>
 #endif
 #include <uapi/linux/in.h>
 
@@ -28,6 +29,7 @@  static void dst_cache_per_cpu_dst_set(struct dst_cache_pcpu *dst_cache,
 				      struct dst_entry *dst, u32 cookie)
 {
 	dst_release(dst_cache->dst);
+
 	if (dst)
 		dst_hold(dst);
 
@@ -98,6 +100,9 @@  void dst_cache_set_ip4(struct dst_cache *dst_cache, struct dst_entry *dst,
 
 	idst = this_cpu_ptr(dst_cache->cache);
 	dst_cache_per_cpu_dst_set(idst, dst, 0);
+	if (dst && list_empty(&dst->rt_uncached))
+		rt_add_uncached_list(dst_rtable(dst));
+
 	idst->in_saddr.s_addr = saddr;
 }
 EXPORT_SYMBOL_GPL(dst_cache_set_ip4);
@@ -114,6 +119,9 @@  void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst,
 	idst = this_cpu_ptr(dst_cache->cache);
 	dst_cache_per_cpu_dst_set(idst, dst,
 				  rt6_get_cookie(dst_rt6_info(dst)));
+	if (dst && list_empty(&dst->rt_uncached))
+		rt6_uncached_list_add(dst_rt6_info(dst));
+
 	idst->in6_saddr = *saddr;
 }
 EXPORT_SYMBOL_GPL(dst_cache_set_ip6);