Skip to content

Commit 00d8c45

Browse files
Florian Westphalgregkh
authored andcommitted
net: core: fix lockdep splat on device unregister
[ Upstream commit 7f0fddd ] Since blamed commit, unregister_netdevice_many_notify() takes the netdev mutex if the device needs it. If the device list is too long, this will lock more device mutexes than lockdep can handle: unshare -n \ bash -c 'for i in $(seq 1 100);do ip link add foo$i type dummy;done' BUG: MAX_LOCK_DEPTH too low! turning off the locking correctness validator. depth: 48 max: 48! 48 locks held by kworker/u16:1/69: #0: ..148 ((wq_completion)netns){+.+.}-{0:0}, at: process_one_work #1: ..d40 (net_cleanup_work){+.+.}-{0:0}, at: process_one_work #2: ..bd0 (pernet_ops_rwsem){++++}-{4:4}, at: cleanup_net #3: ..aa8 (rtnl_mutex){+.+.}-{4:4}, at: default_device_exit_batch #4: ..cb0 (&dev_instance_lock_key#3){+.+.}-{4:4}, at: unregister_netdevice_many_notify [..] Add a helper to close and then unlock a list of net_devices. Devices that are not up have to be skipped - netif_close_many always removes them from the list without any other actions taken, so they'd remain in locked state. Close devices whenever we've used up half of the tracking slots or we processed entire list without hitting the limit. Fixes: 7e4d784 ("net: hold netdev instance lock during rtnetlink operations") Signed-off-by: Florian Westphal <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent be643d3 commit 00d8c45

File tree

1 file changed

+35
-5
lines changed

1 file changed

+35
-5
lines changed

net/core/dev.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12088,6 +12088,35 @@ static void dev_memory_provider_uninstall(struct net_device *dev)
1208812088
}
1208912089
}
1209012090

12091+
/* devices must be UP and netdev_lock()'d */
12092+
static void netif_close_many_and_unlock(struct list_head *close_head)
12093+
{
12094+
struct net_device *dev, *tmp;
12095+
12096+
netif_close_many(close_head, false);
12097+
12098+
/* ... now unlock them */
12099+
list_for_each_entry_safe(dev, tmp, close_head, close_list) {
12100+
netdev_unlock(dev);
12101+
list_del_init(&dev->close_list);
12102+
}
12103+
}
12104+
12105+
static void netif_close_many_and_unlock_cond(struct list_head *close_head)
12106+
{
12107+
#ifdef CONFIG_LOCKDEP
12108+
/* We can only track up to MAX_LOCK_DEPTH locks per task.
12109+
*
12110+
* Reserve half the available slots for additional locks possibly
12111+
* taken by notifiers and (soft)irqs.
12112+
*/
12113+
unsigned int limit = MAX_LOCK_DEPTH / 2;
12114+
12115+
if (lockdep_depth(current) > limit)
12116+
netif_close_many_and_unlock(close_head);
12117+
#endif
12118+
}
12119+
1209112120
void unregister_netdevice_many_notify(struct list_head *head,
1209212121
u32 portid, const struct nlmsghdr *nlh)
1209312122
{
@@ -12120,17 +12149,18 @@ void unregister_netdevice_many_notify(struct list_head *head,
1212012149

1212112150
/* If device is running, close it first. Start with ops locked... */
1212212151
list_for_each_entry(dev, head, unreg_list) {
12152+
if (!(dev->flags & IFF_UP))
12153+
continue;
1212312154
if (netdev_need_ops_lock(dev)) {
1212412155
list_add_tail(&dev->close_list, &close_head);
1212512156
netdev_lock(dev);
1212612157
}
12158+
netif_close_many_and_unlock_cond(&close_head);
1212712159
}
12128-
netif_close_many(&close_head, true);
12129-
/* ... now unlock them and go over the rest. */
12160+
netif_close_many_and_unlock(&close_head);
12161+
/* ... now go over the rest. */
1213012162
list_for_each_entry(dev, head, unreg_list) {
12131-
if (netdev_need_ops_lock(dev))
12132-
netdev_unlock(dev);
12133-
else
12163+
if (!netdev_need_ops_lock(dev))
1213412164
list_add_tail(&dev->close_list, &close_head);
1213512165
}
1213612166
netif_close_many(&close_head, true);

0 commit comments

Comments
 (0)