profiling: remove profile=sleep support

commit b88f55389ad27f05ed84af9e1026aa64dbfabc9a upstream.

The kernel sleep profile is no longer working due to a recursive locking
bug introduced by commit 42a20f86dc ("sched: Add wrapper for get_wchan()
to keep task blocked")

Booting with the 'profile=sleep' kernel command line option added or
executing

  # echo -n sleep > /sys/kernel/profiling

after boot causes the system to lock up.

Lockdep reports

  kthreadd/3 is trying to acquire lock:
  ffff93ac82e08d58 (&p->pi_lock){....}-{2:2}, at: get_wchan+0x32/0x70

  but task is already holding lock:
  ffff93ac82e08d58 (&p->pi_lock){....}-{2:2}, at: try_to_wake_up+0x53/0x370

with the call trace being

   lock_acquire+0xc8/0x2f0
   get_wchan+0x32/0x70
   __update_stats_enqueue_sleeper+0x151/0x430
   enqueue_entity+0x4b0/0x520
   enqueue_task_fair+0x92/0x6b0
   ttwu_do_activate+0x73/0x140
   try_to_wake_up+0x213/0x370
   swake_up_locked+0x20/0x50
   complete+0x2f/0x40
   kthread+0xfb/0x180

However, since nobody noticed this regression for more than two years,
let's remove 'profile=sleep' support based on the assumption that nobody
needs this functionality.

Fixes: 42a20f86dc ("sched: Add wrapper for get_wchan() to keep task blocked")
Cc: stable@vger.kernel.org # v5.16+
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Tetsuo Handa 2024-08-04 18:48:10 +09:00 committed by Greg Kroah-Hartman
parent c265240444
commit 2d451ec01e
4 changed files with 2 additions and 24 deletions

View File

@ -4655,11 +4655,9 @@
profile= [KNL] Enable kernel profiling via /proc/profile profile= [KNL] Enable kernel profiling via /proc/profile
Format: [<profiletype>,]<number> Format: [<profiletype>,]<number>
Param: <profiletype>: "schedule", "sleep", or "kvm" Param: <profiletype>: "schedule" or "kvm"
[defaults to kernel profiling] [defaults to kernel profiling]
Param: "schedule" - profile schedule points. Param: "schedule" - profile schedule points.
Param: "sleep" - profile D-state sleeping (millisecs).
Requires CONFIG_SCHEDSTATS
Param: "kvm" - profile VM exits. Param: "kvm" - profile VM exits.
Param: <number> - step/bucket size as a power of 2 for Param: <number> - step/bucket size as a power of 2 for
statistical time based profiling. statistical time based profiling.

View File

@ -11,7 +11,6 @@
#define CPU_PROFILING 1 #define CPU_PROFILING 1
#define SCHED_PROFILING 2 #define SCHED_PROFILING 2
#define SLEEP_PROFILING 3
#define KVM_PROFILING 4 #define KVM_PROFILING 4
struct proc_dir_entry; struct proc_dir_entry;

View File

@ -57,20 +57,11 @@ static DEFINE_MUTEX(profile_flip_mutex);
int profile_setup(char *str) int profile_setup(char *str)
{ {
static const char schedstr[] = "schedule"; static const char schedstr[] = "schedule";
static const char sleepstr[] = "sleep";
static const char kvmstr[] = "kvm"; static const char kvmstr[] = "kvm";
const char *select = NULL; const char *select = NULL;
int par; int par;
if (!strncmp(str, sleepstr, strlen(sleepstr))) { if (!strncmp(str, schedstr, strlen(schedstr))) {
#ifdef CONFIG_SCHEDSTATS
force_schedstat_enabled();
prof_on = SLEEP_PROFILING;
select = sleepstr;
#else
pr_warn("kernel sleep profiling requires CONFIG_SCHEDSTATS\n");
#endif /* CONFIG_SCHEDSTATS */
} else if (!strncmp(str, schedstr, strlen(schedstr))) {
prof_on = SCHED_PROFILING; prof_on = SCHED_PROFILING;
select = schedstr; select = schedstr;
} else if (!strncmp(str, kvmstr, strlen(kvmstr))) { } else if (!strncmp(str, kvmstr, strlen(kvmstr))) {

View File

@ -92,16 +92,6 @@ void __update_stats_enqueue_sleeper(struct rq *rq, struct task_struct *p,
trace_sched_stat_blocked(p, delta); trace_sched_stat_blocked(p, delta);
/*
* Blocking time is in units of nanosecs, so shift by
* 20 to get a milliseconds-range estimation of the
* amount of time that the task spent sleeping:
*/
if (unlikely(prof_on == SLEEP_PROFILING)) {
profile_hits(SLEEP_PROFILING,
(void *)get_wchan(p),
delta >> 20);
}
account_scheduler_latency(p, delta >> 10, 0); account_scheduler_latency(p, delta >> 10, 0);
} }
} }