The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Rik van Riel <riel@surriel.com>
To: linux-kernel@vger.kernel.org
Cc: kernel-team@meta.com, mingo@redhat.com, peterz@infradead.org,
	juri.lelli@redhat.com, vincent.guittot@linaro.org,
	dietmar.eggemann@arm.com, vschneid@redhat.com,
	Rik van Riel <riel@surriel.com>
Subject: [PATCH 0/9] sched: make WARN_ON under rq->lock deadlock-safe (SCHED_WARN_ON)
Date: Wed, 10 Jun 2026 22:14:07 -0400	[thread overview]
Message-ID: <20260611021416.910555-1-riel@surriel.com> (raw)

A plain WARN_ON()/WARN_ON_ONCE()/WARN()/WARN_ONCE() emits at KERN_WARNING.
On a machine with a legacy or boot console registered (e.g. console=ttyS0),
vprintk_emit() takes the synchronous "legacy_direct" path:

  console_trylock_spinning() + console_unlock()
    -> up(&console_sem) -> wake_up_process() -> try_to_wake_up()

which grabs the woken task's ->pi_lock and its rq->lock.  Almost every WARN
in the scheduling-class hot paths fires while the current CPU already holds
an rq->lock or a ->pi_lock, so this re-enters the scheduler and can deadlock
(recursively on rq->lock, or via the pi_lock/rq->lock order).  The nbcon and
klogd wakeups are deferred via irq_work and are safe; only the legacy console
path is synchronous.

This deadlock bit us when the WARN_ON_ONCE in __sum_w_vruntime_add()
fired, but many other WARN instances in the scheduler code appear to
be vulnerable to the exact same deadlock.

The scheduler already works around this in a handful of spots by using
printk_deferred() instead of printk(), but WARN_ON() has no such variant: it
emits at KERN_WARNING, not LOGLEVEL_SCHED, so it is not deferred.

Patch 1 adds SCHED_WARN_ON()/SCHED_WARN_ON_ONCE() and the SCHED_WARN()/
SCHED_WARN_ONCE() message-carrying forms, which behave exactly like their
WARN*() counterparts but bracket the report in a printk_deferred section so
the console output is handed to irq_work instead of being emitted
synchronously.  The bracket is entered only on the (cold) firing path, so the
hot path cost is unchanged -- just the condition test.  (printk_deferred
toggles a per-CPU counter that must be balanced on one CPU, which is
guaranteed because rq->lock/->pi_lock are raw_spinlock_t and disable
preemption; a lockdep_assert_preemption_disabled() catches misuse and
compiles away without CONFIG_PROVE_LOCKING.)

Patches 2-9 convert, one file at a time (for bisectability), the WARN*()
calls that execute under rq->lock or ->pi_lock.  WARN sites in
setup/teardown/sysfs/preemptible paths are left alone (they are not in the
hazard class and SCHED_WARN_ON would trip the lockdep assert there).

  1  sched: add SCHED_WARN_ON()/.../SCHED_WARN_ONCE()
  2  sched/core              (34 sites)
  3  sched/fair             (33)
  4  sched/deadline         (36)
  5  sched/rt               (17)
  6  sched_ext              (49)
  7  sched/core_sched        (3)
  8  sched/deadline (cpudeadline.c)  (3)
  9  sched/rt (cpupri.c)             (1)

Not converted: two sites with mixed preemptible/locked callers
(nohz_balance_exit_idle() in fair.c, next_task_group() in rt.c) are left as
plain WARN_ON_ONCE() pending per-site analysis -- converting them blindly
would risk a false lockdep_assert_preemption_disabled() on the preemptible
caller path.

Built (full bzImage, x86_64) on tip sched/core.  Based on sched/core plus the
EEVDF reweight vlag-clamp fix; the series itself is independent of that fix.

Split up into one patch per .c file in kernel/sched to make things a
little less unwieldy.

Rik van Riel (9):
  sched: add SCHED_WARN_ON()/SCHED_WARN_ON_ONCE()/SCHED_WARN()/SCHED_WARN_ONCE()
  sched/core: defer WARN console output under rq->lock
  sched/fair: defer WARN console output under rq->lock
  sched/deadline: defer WARN console output under rq->lock
  sched/rt: defer WARN console output under rq->lock
  sched_ext: defer WARN console output under rq->lock
  sched/core_sched: defer WARN console output under rq->lock
  sched/deadline: defer WARN console output under rq->lock
  sched/rt: defer WARN console output under rq->lock

 kernel/sched/core.c        | 68 +++++++++++++-------------
 kernel/sched/core_sched.c  |  6 +--
 kernel/sched/cpudeadline.c |  6 +--
 kernel/sched/cpupri.c      |  2 +-
 kernel/sched/deadline.c    | 72 ++++++++++++++--------------
 kernel/sched/ext.c         | 98 +++++++++++++++++++-------------------
 kernel/sched/fair.c        | 66 ++++++++++++-------------
 kernel/sched/rt.c          | 34 ++++++-------
 kernel/sched/sched.h       | 52 ++++++++++++++++++++
 9 files changed, 228 insertions(+), 176 deletions(-)


base-commit: eaf710f74e602ea2fd517f798066d6988072f3ae
-- 
2.53.0-Meta


             reply	other threads:[~2026-06-11  2:14 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-11  2:14 Rik van Riel [this message]
2026-06-11  2:14 ` [PATCH 1/9] sched: add SCHED_WARN_ON()/SCHED_WARN_ON_ONCE()/SCHED_WARN()/SCHED_WARN_ONCE() Rik van Riel
2026-06-11  2:14 ` [PATCH 2/9] sched/core: defer WARN console output under rq->lock Rik van Riel
2026-06-11  2:14 ` [PATCH 3/9] sched/fair: " Rik van Riel
2026-06-11  2:14 ` [PATCH 4/9] sched/deadline: " Rik van Riel
2026-06-11  2:14 ` [PATCH 5/9] sched/rt: " Rik van Riel
2026-06-11  2:14 ` [PATCH 6/9] sched_ext: " Rik van Riel
2026-06-11  2:14 ` [PATCH 7/9] sched/core_sched: " Rik van Riel
2026-06-11  2:14 ` [PATCH 8/9] sched/deadline: " Rik van Riel
2026-06-11  2:14 ` [PATCH 9/9] sched/rt: " Rik van Riel
2026-06-11  7:43 ` [PATCH 0/9] sched: make WARN_ON under rq->lock deadlock-safe (SCHED_WARN_ON) Peter Zijlstra
2026-06-11 16:20   ` Rik van Riel
2026-06-11 19:19     ` Peter Zijlstra
2026-06-12  1:53       ` Rik van Riel
2026-06-12  6:52         ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260611021416.910555-1-riel@surriel.com \
    --to=riel@surriel.com \
    --cc=dietmar.eggemann@arm.com \
    --cc=juri.lelli@redhat.com \
    --cc=kernel-team@meta.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox