1 From 60f92acb60a989b14e4b744501a0df0f82ef30a3 Mon Sep 17 00:00:00 2001
2 From: Oleg Nesterov <oleg@redhat.com>
3 Date: Tue, 23 Jan 2024 16:33:55 +0100
4 Subject: fs/proc: do_task_stat: move thread_group_cputime_adjusted() outside of lock_task_sighand()
6 From: Oleg Nesterov <oleg@redhat.com>
8 commit 60f92acb60a989b14e4b744501a0df0f82ef30a3 upstream.
10 Patch series "fs/proc: do_task_stat: use sig->stats_".
12 do_task_stat() has the same problem as getrusage() had before "getrusage:
13 use sig->stats_lock rather than lock_task_sighand()": a hard lockup. If
14 NR_CPUS threads call lock_task_sighand() at the same time and the process
15 has NR_THREADS, spin_lock_irq will spin with irqs disabled O(NR_CPUS *
21 thread_group_cputime() does its own locking, we can safely shift
22 thread_group_cputime_adjusted() which does another for_each_thread loop
23 outside of ->siglock protected section.
25 Not only this removes for_each_thread() from the critical section with
26 irqs disabled, this removes another case when stats_lock is taken with
27 siglock held. We want to remove this dependency, then we can change the
28 users of stats_lock to not disable irqs.
30 Link: https://lkml.kernel.org/r/20240123153313.GA21832@redhat.com
31 Link: https://lkml.kernel.org/r/20240123153355.GA21854@redhat.com
32 Signed-off-by: Oleg Nesterov <oleg@redhat.com>
33 Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
34 Cc: Eric W. Biederman <ebiederm@xmission.com>
35 Cc: <stable@vger.kernel.org>
36 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
37 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
39 fs/proc/array.c | 10 ++++++----
40 1 file changed, 6 insertions(+), 4 deletions(-)
44 @@ -511,7 +511,7 @@ static int do_task_stat(struct seq_file
47 sigemptyset(&sigcatch);
48 - cutime = cstime = utime = stime = 0;
49 + cutime = cstime = 0;
52 if (lock_task_sighand(task, &flags)) {
53 @@ -546,7 +546,6 @@ static int do_task_stat(struct seq_file
55 min_flt += sig->min_flt;
56 maj_flt += sig->maj_flt;
57 - thread_group_cputime_adjusted(task, &utime, &stime);
60 if (sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED))
61 @@ -562,10 +561,13 @@ static int do_task_stat(struct seq_file
63 if (permitted && (!whole || num_threads < 2))
64 wchan = !task_is_running(task);
68 + thread_group_cputime_adjusted(task, &utime, &stime);
70 + task_cputime_adjusted(task, &utime, &stime);
71 min_flt = task->min_flt;
72 maj_flt = task->maj_flt;
73 - task_cputime_adjusted(task, &utime, &stime);
74 gtime = task_gtime(task);