diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2026-08-24 12:49:10 +0200 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2026-08-24 12:58:54 +0200 |
| commit | 46094a7708b7945cb7eba9eb887e3ea9757440a7 (patch) | |
| tree | 424a54358fe0ccf9ce550e32fa8a24b0c49aa62e /kernel | |
| parent | 0a0d1d55dad570724bf8c7ea83409639cfb4be9b (diff) | |
locking: Revert switching guards to _irq_{disable,enable}()
Revert commit 1b0866874833 ("locking: Switch to _irq_{disable,enable}()
variants in cleanup guards").
While the guards are properly nested, not all wrapped code is nice, as already
highlighted by that fair.c hunk.
Syzbot found another instance of this pattern in posix_timer_delete(), which
does spin_unlock_irq()+spin_lock_irq() inside scoped_guard(spinlock_irq).
Combined with this patch, that goes sideways most spectacular.
Undo this until we've developed stronger tools / debug for such issues.
Fixes: 1b0866874833 ("locking: Switch to _irq_{disable,enable}() variants in cleanup guards")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260824105523.GA4121620%40noisy.programming.kicks-ass.net
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/fair.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6d881e530f89..8dff37059faf 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7253,7 +7253,7 @@ static bool distribute_cfs_runtime(struct cfs_bandwidth *cfs_b) * period the timer is deactivated until scheduling resumes; cfs_b->idle is * used to track this state. */ -static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun) +static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, unsigned long flags) __must_hold(&cfs_b->lock) { int throttled; @@ -7288,10 +7288,10 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun) * This check is repeated as we release cfs_b->lock while we unthrottle. */ while (throttled && cfs_b->runtime > 0) { - raw_spin_unlock_irq_enable(&cfs_b->lock); + raw_spin_unlock_irqrestore(&cfs_b->lock, flags); /* we can't nest cfs_b->lock while distributing bandwidth */ throttled = distribute_cfs_runtime(cfs_b); - raw_spin_lock_irq_disable(&cfs_b->lock); + raw_spin_lock_irqsave(&cfs_b->lock, flags); } /* @@ -7399,7 +7399,7 @@ static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) { /* confirm we're still not at a refresh boundary */ - scoped_guard(raw_spinlock_irq, &cfs_b->lock) { + scoped_guard(raw_spinlock_irqsave, &cfs_b->lock) { u64 runtime = 0, slice = sched_cfs_bandwidth_slice(); cfs_b->slack_started = false; @@ -7484,14 +7484,14 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer) int idle = 0; int count = 0; - guard(raw_spinlock_irq)(&cfs_b->lock); + CLASS(raw_spinlock_irqsave, cfsb_guard)(&cfs_b->lock); for (;;) { overrun = hrtimer_forward_now(timer, cfs_b->period); if (!overrun) break; - idle = do_sched_cfs_period_timer(cfs_b, overrun); + idle = do_sched_cfs_period_timer(cfs_b, overrun, cfsb_guard.flags); if (++count > 3) { u64 new, old = ktime_to_ns(cfs_b->period); |
