Re: [RFC PATCH] mm: restrict can_spin_trylock() to preemptible context on PREEMPT_RT
From: Alexei Starovoitov
Date: Sat Sep 19 2026 - 14:18:21 EST
On Sat, Sep 19, 2026 at 07:14 PM Karl Mehltretter <kmehltretter@xxxxxxxxx> wrote:
> Allow preemptible context only, as v6.19 did. A held raw spinlock
> implies !preemptible(), so the locks of the caller do not have to be
> known. With this change both machines pass 10 of 10 boots.
>
> The nolock allocations then fail on PREEMPT_RT from every context with
> preemption or interrupts disabled, also where no scheduler lock is
> held. Creation of BPF local storage from such a context fails, as it
> did in v6.19.
6.19 had this check in kmalloc_nolock() only. alloc_pages_nolock() and
free_pages_nolock() allowed irqs disabled since they were introduced,
and arena was sleepable only under a mutex back then.
[...]
> diff --git a/mm/internal.h b/mm/internal.h
> index 38b1165212c94..29646c4afb419 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -1641,10 +1641,14 @@ static inline bool can_spin_trylock(void)
[...]
> - if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi()
|| in_hardirq()))
> + if (IS_ENABLED(CONFIG_PREEMPT_RT) && !preemptible())
> return false;
No. This kills bpf arena on RT.
Since 7.0 arena_alloc_pages() and arena_vm_fault() take
raw_res_spin_lock_irqsave(&arena->spinlock) and call
alloc_pages_nolock() and kmalloc_nolock() (from range_tree) under it.
With !preemptible() here bpf_arena_alloc_pages() returns NULL for every
prog, sleepable included, and a user space fault in arena gets SIGSEGV.
As Sebastian said in
https://lore.kernel.org/r/20260831143500.x-saxdAs@xxxxxxxxxxxxx
raw_spinlock_t is fine in general. pi_lock is special. rq lock too,
I think, since rt_spin_unlock() can end up in try_to_wake_up().
The check has to be about those and not about every irq/preempt
disabled section.
pw-bot: cr