Skip to content

Commit

Permalink
net: make netdev_lock() protect netdev->reg_state
Browse files Browse the repository at this point in the history
Protect writes to netdev->reg_state with netdev_lock().
From now on holding netdev_lock() is sufficient to prevent
the net_device from getting unregistered, so code which
wants to hold just a single netdev around no longer needs
to hold rtnl_lock.

We do not protect the NETREG_UNREGISTERED -> NETREG_RELEASED
transition. We'd need to move mutex_destroy(netdev->lock)
to .release, but the real reason is that trying to stop
the unregistration process mid-way would be unsafe / crazy.
Taking references on such devices is not safe, either.
So the intended semantics are to lock REGISTERED devices.

Reviewed-by: Joe Damato <jdamato@fastly.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250115035319.559603-3-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
kuba-moo committed Jan 16, 2025
1 parent ebda2f0 commit 5fda3f3
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 1 deletion.
2 changes: 1 addition & 1 deletion include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2448,7 +2448,7 @@ struct net_device {
* Should always be taken using netdev_lock() / netdev_unlock() helpers.
* Drivers are free to use it for other protection.
*
* Protects: @net_shaper_hierarchy.
* Protects: @reg_state, @net_shaper_hierarchy.
* Ordering: take after rtnl_lock.
*/
struct mutex lock;
Expand Down
6 changes: 6 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -10695,7 +10695,9 @@ int register_netdevice(struct net_device *dev)

ret = netdev_register_kobject(dev);

netdev_lock(dev);
WRITE_ONCE(dev->reg_state, ret ? NETREG_UNREGISTERED : NETREG_REGISTERED);
netdev_unlock(dev);

if (ret)
goto err_uninit_notify;
Expand Down Expand Up @@ -10969,7 +10971,9 @@ void netdev_run_todo(void)
continue;
}

netdev_lock(dev);
WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERED);
netdev_unlock(dev);
linkwatch_sync_dev(dev);
}

Expand Down Expand Up @@ -11575,7 +11579,9 @@ void unregister_netdevice_many_notify(struct list_head *head,
list_for_each_entry(dev, head, unreg_list) {
/* And unlink it from device chain. */
unlist_netdevice(dev);
netdev_lock(dev);
WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERING);
netdev_unlock(dev);
}
flush_all_backlogs();

Expand Down

0 comments on commit 5fda3f3

Please sign in to comment.