Message ID | 20220207171756.1304544-12-eric.dumazet@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net: speedup netns dismantles | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Clearly marked for net-next |
netdev/fixes_present | success | Fixes tag not required for -next series |
netdev/subject_prefix | success | Link |
netdev/cover_letter | success | Series has a cover letter |
netdev/patch_count | success | Link |
netdev/header_inline | success | No static functions without inline keyword in header files |
netdev/build_32bit | fail | Errors and warnings before: 13 this patch: 13 |
netdev/cc_maintainers | success | CCed 4 of 4 maintainers |
netdev/build_clang | fail | Errors and warnings before: 6 this patch: 6 |
netdev/module_param | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Signed-off-by tag matches author and committer |
netdev/verify_fixes | success | No Fixes tag |
netdev/build_allmodconfig_warn | fail | Errors and warnings before: 13 this patch: 13 |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 75 lines checked |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/source_inline | success | Was 0 now: 0 |
On 2/7/22 9:17 AM, Eric Dumazet wrote: > From: Eric Dumazet <edumazet@google.com> > > For some reason default_device_ops kept two exit method: > > 1) default_device_exit() is called for each netns being dismantled in > a cleanup_net() round. This acquires rtnl for each invocation. > > 2) default_device_exit_batch() is called once with the list of all netns > int the batch, allowing for a single rtnl invocation. > > Get rid of the .exit() method to handle the logic from > default_device_exit_batch(), to decrease the number of rtnl acquisition > to one. > > Signed-off-by: Eric Dumazet <edumazet@google.com> > --- > net/core/dev.c | 22 ++++++++++++++-------- > 1 file changed, 14 insertions(+), 8 deletions(-) > Reviewed-by: David Ahern <dsahern@kernel.org>
On Mon, Feb 7, 2022 at 8:29 PM David Ahern <dsahern@gmail.com> wrote: > > On 2/7/22 9:17 AM, Eric Dumazet wrote: > > From: Eric Dumazet <edumazet@google.com> > > > > For some reason default_device_ops kept two exit method: > > > > 1) default_device_exit() is called for each netns being dismantled in > > a cleanup_net() round. This acquires rtnl for each invocation. > > > > 2) default_device_exit_batch() is called once with the list of all netns > > int the batch, allowing for a single rtnl invocation. > > > > Get rid of the .exit() method to handle the logic from > > default_device_exit_batch(), to decrease the number of rtnl acquisition > > to one. > > > > Signed-off-by: Eric Dumazet <edumazet@google.com> > > --- > > net/core/dev.c | 22 ++++++++++++++-------- > > 1 file changed, 14 insertions(+), 8 deletions(-) > > > > Reviewed-by: David Ahern <dsahern@kernel.org> Thanks for the review ! I am sending a v2, with your tags, plus the RTNL_ASSERT() typo fixed.
diff --git a/net/core/dev.c b/net/core/dev.c index f662c6a7d7b49b836a05efc74aeffc7fc9e4e147..e39c2897f6475dfa77c478603cfced76ba0b9078 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -10848,14 +10848,14 @@ static struct pernet_operations __net_initdata netdev_net_ops = { .exit = netdev_exit, }; -static void __net_exit default_device_exit(struct net *net) +static void __net_exit default_device_exit_net(struct net *net) { struct net_device *dev, *aux; /* * Push all migratable network devices back to the * initial network namespace */ - rtnl_lock(); + ASSERT_RTNL(); for_each_netdev_safe(net, dev, aux) { int err; char fb_name[IFNAMSIZ]; @@ -10879,22 +10879,22 @@ static void __net_exit default_device_exit(struct net *net) BUG(); } } - rtnl_unlock(); } static void __net_exit rtnl_lock_unregistering(struct list_head *net_list) { - /* Return with the rtnl_lock held when there are no network + /* Return (with the rtnl_lock held) when there are no network * devices unregistering in any network namespace in net_list. */ - struct net *net; - bool unregistering; DEFINE_WAIT_FUNC(wait, woken_wake_function); + bool unregistering; + struct net *net; + ASSERT_RTNL(); add_wait_queue(&netdev_unregistering_wq, &wait); for (;;) { unregistering = false; - rtnl_lock(); + list_for_each_entry(net, net_list, exit_list) { if (net->dev_unreg_count > 0) { unregistering = true; @@ -10906,6 +10906,7 @@ static void __net_exit rtnl_lock_unregistering(struct list_head *net_list) __rtnl_unlock(); wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); + rtnl_lock(); } remove_wait_queue(&netdev_unregistering_wq, &wait); } @@ -10921,6 +10922,11 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list) 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(); + } /* To prevent network device cleanup code from dereferencing * loopback devices or network devices that have been freed * wait here for all pending unregistrations to complete, @@ -10933,6 +10939,7 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list) * default_device_exit_batch. */ rtnl_lock_unregistering(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) @@ -10946,7 +10953,6 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list) } static struct pernet_operations __net_initdata default_device_ops = { - .exit = default_device_exit, .exit_batch = default_device_exit_batch, };