After unshare test kworker hangs for ages: $ while :; do unshare -n true; done &
$ perf report <kworker> - 88,82% 0,00% kworker/u16:0 [kernel.vmlinux] [k] cleanup_net cleanup_net - ops_exit_list.isra.9 - 85,68% igmp6_net_exit - 53,31% sock_release - inet_release - 25,33% rawv6_close - ip6mr_sk_done + 23,38% synchronize_rcu Keep in mind, this perf report shows the time a function was executing, and it does not show the time, it was sleeping. But it's easy to imagine, how much it is sleeping, if synchronize_rcu() execution takes the most time. Top shows the kworker R time is less then 1%. This happen, because of in ip6mr_sk_done() we do too many synchronize_rcu(), even for the sockets, that are not referenced in mr_table, and which are not need it. So, the progress of kworker becomes very slow. The patch introduces apparent solution, and it makes ip6mr_sk_done() to skip synchronize_rcu() for sockets, that are not need that. After the patch, kworker becomes able to warm the cpu up as expected. Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com> --- net/ipv6/ip6mr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 2a38f9de45d3..290a8d0d5eac 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1485,7 +1485,9 @@ int ip6mr_sk_done(struct sock *sk) } } rtnl_unlock(); - synchronize_rcu(); + + if (!err) + synchronize_rcu(); return err; }