diff mbox series

[net-next] net: introduce netdev_napi_exit()

Message ID 20250117232113.1612899-1-edumazet@google.com (mailing list archive)
State New
Delegated to: Netdev Maintainers
Headers show
Series [net-next] net: introduce netdev_napi_exit() | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
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 success Errors and warnings before: 0 this patch: 0
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 2 this patch: 2
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 No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 5 this patch: 5
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 41 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 79 this patch: 79
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2025-01-18--03-00 (tests: 887)

Commit Message

Eric Dumazet Jan. 17, 2025, 11:21 p.m. UTC
After 1b23cdbd2bbc ("net: protect netdev->napi_list with netdev_lock()")
it makes sense to iterate through dev->napi_list while holding
the device lock.

Also call synchronize_net() at most one time.

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/core/dev.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

Comments

Jakub Kicinski Jan. 18, 2025, 1:24 a.m. UTC | #1
On Fri, 17 Jan 2025 23:21:13 +0000 Eric Dumazet wrote:
> After 1b23cdbd2bbc ("net: protect netdev->napi_list with netdev_lock()")
> it makes sense to iterate through dev->napi_list while holding
> the device lock.
> 
> Also call synchronize_net() at most one time.

I suspected you may send this :)

I was wondering whether we have to call sync_rcu() at all, Joe moved
unhashing the NAPI to napi_disable(). Assuming the driver is sane 
it will call napi_disable() at latest in ndo_uninit(), and there's
already a synchronize_net() between ndo_uninit() and free.

But maybe drivers are not sane. We don't have

	/* napi_disable() sets the SCHED bit */
	WARN_ON(!test_bit(NAPI_STATE_SCHED, &val));

in netif_napi_del(). I think we should add it, after Joe's changes
if driver doesn't disable the napi it will leave a stale pointer
in the hash table.

In any case, your change makes sense:

Reviewed-by: Jakub Kicinski <kuba@kernel.org>
diff mbox series

Patch

diff --git a/net/core/dev.c b/net/core/dev.c
index fab4899b83f745a3c13c982775e287b1ff2f547d..d7cbe6ff5249a5c22dd7e0e4c929a535e1f28612 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11568,6 +11568,22 @@  struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
 }
 EXPORT_SYMBOL(alloc_netdev_mqs);
 
+static void netdev_napi_exit(struct net_device *dev)
+{
+	if (!list_empty(&dev->napi_list)) {
+		struct napi_struct *p, *n;
+
+		netdev_lock(dev);
+		list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
+			__netif_napi_del_locked(p);
+		netdev_unlock(dev);
+
+		synchronize_net();
+	}
+
+	kvfree(dev->napi_config);
+}
+
 /**
  * free_netdev - free network device
  * @dev: device
@@ -11579,8 +11595,6 @@  EXPORT_SYMBOL(alloc_netdev_mqs);
  */
 void free_netdev(struct net_device *dev)
 {
-	struct napi_struct *p, *n;
-
 	might_sleep();
 
 	/* When called immediately after register_netdevice() failed the unwind
@@ -11602,10 +11616,7 @@  void free_netdev(struct net_device *dev)
 	/* Flush device addresses */
 	dev_addr_flush(dev);
 
-	list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
-		netif_napi_del(p);
-
-	kvfree(dev->napi_config);
+	netdev_napi_exit(dev);
 
 	ref_tracker_dir_exit(&dev->refcnt_tracker);
 #ifdef CONFIG_PCPU_DEV_REFCNT