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/vmalloc: support non-blocking GFP flags in alloc_vmap_area()

alloc_vmap_area() currently assumes that sleeping is allowed during
allocation. This is not true for callers which pass non-blocking GFP
flags, such as GFP_ATOMIC or GFP_NOWAIT.

This patch adds logic to detect whether the given gfp_mask permits
blocking. It avoids invoking might_sleep() or falling back to reclaim
path if blocking is not allowed.

This makes alloc_vmap_area() safer for use in non-sleeping contexts, where
previously it could hit unexpected sleeps, trigger warnings.

It is a preparation and adjustment step to later allow both GFP_ATOMIC and
GFP_NOWAIT allocations in this series.

Link: https://lkml.kernel.org/r/20251007122035.56347-4-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
86e968d8 e781c1c0

+16 -4
+16 -4
mm/vmalloc.c
··· 2017 2017 unsigned long freed; 2018 2018 unsigned long addr; 2019 2019 unsigned int vn_id; 2020 + bool allow_block; 2020 2021 int purged = 0; 2021 2022 int ret; 2022 2023 ··· 2029 2028 2030 2029 /* Only reclaim behaviour flags are relevant. */ 2031 2030 gfp_mask = gfp_mask & GFP_RECLAIM_MASK; 2032 - might_sleep(); 2031 + allow_block = gfpflags_allow_blocking(gfp_mask); 2032 + might_sleep_if(allow_block); 2033 2033 2034 2034 /* 2035 2035 * If a VA is obtained from a global heap(if it fails here) ··· 2064 2062 * This is not a fast path. Check if yielding is needed. This 2065 2063 * is the only reschedule point in the vmalloc() path. 2066 2064 */ 2067 - cond_resched(); 2065 + if (allow_block) 2066 + cond_resched(); 2068 2067 } 2069 2068 2070 2069 trace_alloc_vmap_area(addr, size, align, vstart, vend, IS_ERR_VALUE(addr)); ··· 2074 2071 * If an allocation fails, the error value is 2075 2072 * returned. Therefore trigger the overflow path. 2076 2073 */ 2077 - if (IS_ERR_VALUE(addr)) 2078 - goto overflow; 2074 + if (IS_ERR_VALUE(addr)) { 2075 + if (allow_block) 2076 + goto overflow; 2077 + 2078 + /* 2079 + * We can not trigger any reclaim logic because 2080 + * sleeping is not allowed, thus fail an allocation. 2081 + */ 2082 + goto out_free_va; 2083 + } 2079 2084 2080 2085 va->va_start = addr; 2081 2086 va->va_end = addr + size; ··· 2133 2122 pr_warn("vmalloc_node_range for size %lu failed: Address range restricted to %#lx - %#lx\n", 2134 2123 size, vstart, vend); 2135 2124 2125 + out_free_va: 2136 2126 kmem_cache_free(vmap_area_cachep, va); 2137 2127 return ERR_PTR(-EBUSY); 2138 2128 }