On Sat, Nov 16, 2024 at 1:34 PM Alexei Starovoitov <alexei.starovoitov@xxxxxxxxx> wrote: > > On Sat, Nov 16, 2024 at 1:13 PM Alexei Starovoitov > <alexei.starovoitov@xxxxxxxxx> wrote: > > > > On Sat, Nov 16, 2024 at 11:42 AM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote: > > > > > > On Fri, Nov 15, 2024 at 05:48:53PM -0800, Alexei Starovoitov wrote: > > > > +static inline struct page *try_alloc_page_noprof(int nid) > > > > +{ > > > > + /* If spin_locks are not held and interrupts are enabled, use normal path. */ > > > > + if (preemptible()) > > > > + return alloc_pages_node_noprof(nid, GFP_NOWAIT | __GFP_ZERO, 0); > > > > > > This isn't right for PREEMPT_RT, spinlock_t will be preemptible, but you > > > very much do not want regular allocation calls while inside the > > > allocator itself for example. > > > > I'm aware that spinlocks are preemptible in RT. > > Here is my understanding of why the above is correct... > > - preemptible() means that IRQs are not disabled and preempt_count == 0. > > > > - All page alloc operations are protected either by > > pcp_spin_trylock() or by spin_lock_irqsave(&zone->lock, flags) > > or both together. > > > > - In non-RT spin_lock_irqsave disables IRQs, so preemptible() > > check guarantees that we're not holding zone->lock. > > The page alloc logic can hold pcp lock when try_alloc_page() is called, > > but it's always using pcp_trylock, so it's still ok to call it > > with GFP_NOWAIT. pcp trylock will fail and zone->lock will proceed > > to acquire zone->lock. > > > > - In RT spin_lock_irqsave doesn't disable IRQs despite its name. > > It calls rt_spin_lock() which calls rcu_read_lock() > > which increments preempt_count. > > The maze of ifdef-s beat me :( > It doesn't increment in PREEMPT_RCU. > Need an additional check then. hmm. Like: if (preemptible() && !rcu_preempt_depth()) return alloc_pages_node_noprof(nid, GFP_NOWAIT | __GFP_ZERO, 0); Not pretty, but should do. wdyt?