2026-08-22
The asker is writing a kernel module that needs to allocate several gigabytes of virtually-contiguous memory. They want fail-fast semantics: if the memory isn't available immediately, return NULL rather than block waiting for reclaim or compaction. They noticed __vmalloc() accepts a GFP mask and reasonably ask: does passing GFP_NOWAIT actually guarantee the call won't sleep?
Why this is hard: The GFP contract is straightforward for kmalloc/alloc_pages: __GFP_DIRECT_RECLAIM is the "may sleep" bit, and GFP_NOWAIT clears it. But vmalloc is not a simple page allocator. It does at least three things that can each block independently:
alloc_vmap_area) — this takes a spinlock, but under fragmentation may need to purge lazy-freed areas, which historically has taken mutexes.vmap_pages_range), which itself needs to allocate PTE/PMD pages — and here's the gotcha: those internal allocations historically used GFP_KERNEL, not the caller's flags.The direction to a real answer: Look at mm/vmalloc.c in the version you're targeting. Since ~5.2, __vmalloc_node_range() propagates the caller's gfp_mask to alloc_pages_bulk and, importantly, Michal Hocko's series ensured page-table allocations in the vmap path honor GFP_NOWAIT when passed. So on a modern kernel, __vmalloc(size, GFP_NOWAIT) should be non-blocking for the allocation itself. But:
alloc_vmap_area can still call cond_resched() paths and, when the vmap space is fragmented, trigger purge_vmap_area_lazy() which grabs vmap_purge_lock (a mutex). At multi-GB sizes this is not hypothetical.__GFP_DIRECT_RECLAIM will almost certainly fail on a running system — GFP_NOWAIT only draws from free lists and per-CPU caches. You're asking the allocator to hand you millions of 4K pages from what's already immediately available.GFP_ATOMIC, and even then vmap-area purge can be a hazard — consider pre-allocating at module init.Practical suggestion: pre-reserve the vmalloc region with get_vm_area() at init when sleeping is fine, then populate lazily. Or use vmalloc_huge() to reduce PTE pressure. If it must be runtime, wrap the call in might_sleep()-assertion tests (CONFIG_DEBUG_ATOMIC_SLEEP) on your target kernel to empirically confirm.
vmalloc's GFP contract is subtler than the page allocator's because the call has multiple internal allocation sites (vmap area, backing pages, page-table pages) that each need to honor the flag — and historically not all of them did.