@@ -11596,7 +11596,8 @@ static void __net_exit default_device_exit_net(struct net *net)
}
}
-static void __net_exit default_device_exit_batch(struct list_head *net_list)
+static void __net_exit default_device_exit_batch_rtnl(struct list_head *net_list,
+ struct list_head *dev_kill_list)
{
/* At exit all network devices most be removed from a network
* namespace. Do this in the reverse order of registration.
@@ -11605,9 +11606,7 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list)
*/
struct net_device *dev;
struct net *net;
- LIST_HEAD(dev_kill_list);
- rtnl_lock();
list_for_each_entry(net, net_list, exit_list) {
default_device_exit_net(net);
cond_resched();
@@ -11616,17 +11615,15 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list)
list_for_each_entry(net, net_list, exit_list) {
for_each_netdev_reverse(net, dev) {
if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink)
- dev->rtnl_link_ops->dellink(dev, &dev_kill_list);
+ dev->rtnl_link_ops->dellink(dev, dev_kill_list);
else
- unregister_netdevice_queue(dev, &dev_kill_list);
+ unregister_netdevice_queue(dev, dev_kill_list);
}
}
- unregister_netdevice_many(&dev_kill_list);
- rtnl_unlock();
}
static struct pernet_operations __net_initdata default_device_ops = {
- .exit_batch = default_device_exit_batch,
+ .exit_batch_rtnl = default_device_exit_batch_rtnl,
};
static void __init net_dev_struct_check(void)
exit_batch_rtnl() is called while RTNL is held, and devices to be unregistered can be queued in the dev_kill_list. This saves one rtnl_lock()/rtnl_unlock() pair, and one unregister_netdevice_many() call. Signed-off-by: Eric Dumazet <edumazet@google.com> --- net/core/dev.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)