Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm: kvmalloc: add non-blocking support for vmalloc

Extend __kvmalloc_node_noprof() to handle non-blocking GFP flags
(GFP_NOWAIT and GFP_ATOMIC). Previously such flags were rejected,
returning NULL. With this change:

- kvmalloc() can fall back to vmalloc() if non-blocking contexts;
- for non-blocking allocations the VM_ALLOW_HUGE_VMAP option is
disabled, since the huge mapping path still contains might_sleep();
- documentation update to reflect that GFP_NOWAIT and GFP_ATOMIC
are now supported.

Link: https://lkml.kernel.org/r/20251007122035.56347-11-urezki@gmail.com
Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: Baoquan He <bhe@redhat.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Marco Elver <elver@google.com>
Cc: Michal Hocko <mhocko@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Uladzislau Rezki (Sony) and committed by
Andrew Morton
c6307674 0667b209

+13 -6
+13 -6
mm/slub.c
··· 7090 7090 * Uses kmalloc to get the memory but if the allocation fails then falls back 7091 7091 * to the vmalloc allocator. Use kvfree for freeing the memory. 7092 7092 * 7093 - * GFP_NOWAIT and GFP_ATOMIC are not supported, neither is the __GFP_NORETRY modifier. 7093 + * GFP_NOWAIT and GFP_ATOMIC are supported, the __GFP_NORETRY modifier is not. 7094 7094 * __GFP_RETRY_MAYFAIL is supported, and it should be used only if kmalloc is 7095 7095 * preferable to the vmalloc fallback, due to visible performance drawbacks. 7096 7096 * ··· 7099 7099 void *__kvmalloc_node_noprof(DECL_BUCKET_PARAMS(size, b), unsigned long align, 7100 7100 gfp_t flags, int node) 7101 7101 { 7102 + bool allow_block; 7102 7103 void *ret; 7103 7104 7104 7105 /* ··· 7112 7111 if (ret || size <= PAGE_SIZE) 7113 7112 return ret; 7114 7113 7115 - /* non-sleeping allocations are not supported by vmalloc */ 7116 - if (!gfpflags_allow_blocking(flags)) 7117 - return NULL; 7118 - 7119 7114 /* Don't even allow crazy sizes */ 7120 7115 if (unlikely(size > INT_MAX)) { 7121 7116 WARN_ON_ONCE(!(flags & __GFP_NOWARN)); 7122 7117 return NULL; 7123 7118 } 7119 + 7120 + /* 7121 + * For non-blocking the VM_ALLOW_HUGE_VMAP is not used 7122 + * because the huge-mapping path in vmalloc contains at 7123 + * least one might_sleep() call. 7124 + * 7125 + * TODO: Revise huge-mapping path to support non-blocking 7126 + * flags. 7127 + */ 7128 + allow_block = gfpflags_allow_blocking(flags); 7124 7129 7125 7130 /* 7126 7131 * kvmalloc() can always use VM_ALLOW_HUGE_VMAP, ··· 7135 7128 * protection games. 7136 7129 */ 7137 7130 return __vmalloc_node_range_noprof(size, align, VMALLOC_START, VMALLOC_END, 7138 - flags, PAGE_KERNEL, VM_ALLOW_HUGE_VMAP, 7131 + flags, PAGE_KERNEL, allow_block ? VM_ALLOW_HUGE_VMAP:0, 7139 7132 node, __builtin_return_address(0)); 7140 7133 } 7141 7134 EXPORT_SYMBOL(__kvmalloc_node_noprof);