aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stackdepot.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <[email protected]>2025-02-22 02:44:24 +0000
committerAlexei Starovoitov <[email protected]>2025-02-27 17:36:18 +0000
commit8c57b687e8331eb80e302a2c528b18b966a9ac7a (patch)
tree4ce4359d87a9b34917d0e41359f2ed2dfa3b6e40 /lib/stackdepot.c
parentmm, bpf: Introduce try_alloc_pages() for opportunistic page allocation (diff)
downloadkernel-8c57b687e8331eb80e302a2c528b18b966a9ac7a.tar.gz
kernel-8c57b687e8331eb80e302a2c528b18b966a9ac7a.zip
mm, bpf: Introduce free_pages_nolock()
Introduce free_pages_nolock() that can free pages without taking locks. It relies on trylock and can be called from any context. Since spin_trylock() cannot be used in PREEMPT_RT from hard IRQ or NMI it uses lockless link list to stash the pages which will be freed by subsequent free_pages() from good context. Do not use llist unconditionally. BPF maps continuously allocate/free, so we cannot unconditionally delay the freeing to llist. When the memory becomes free make it available to the kernel and BPF users right away if possible, and fallback to llist as the last resort. Acked-by: Vlastimil Babka <[email protected]> Acked-by: Sebastian Andrzej Siewior <[email protected]> Reviewed-by: Shakeel Butt <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
Diffstat (limited to 'lib/stackdepot.c')
-rw-r--r--lib/stackdepot.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 377194969e61..73d7b50924ef 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -672,7 +672,10 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
exit:
if (prealloc) {
/* Stack depot didn't use this memory, free it. */
- free_pages((unsigned long)prealloc, DEPOT_POOL_ORDER);
+ if (!allow_spin)
+ free_pages_nolock(virt_to_page(prealloc), DEPOT_POOL_ORDER);
+ else
+ free_pages((unsigned long)prealloc, DEPOT_POOL_ORDER);
}
if (found)
handle = found->handle.handle;