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: handle non-blocking GFP in __vmalloc_area_node()

Make __vmalloc_area_node() respect non-blocking GFP masks such as
GFP_ATOMIC and GFP_NOWAIT.

- Add memalloc_apply_gfp_scope()/memalloc_restore_scope()
helpers to apply a proper scope.
- Apply memalloc_apply_gfp_scope()/memalloc_restore_scope()
around vmap_pages_range() for page table setup.
- Set "nofail" to false if a non-blocking mask is used, as
they are mutually exclusive.

This is particularly important for page table allocations that internally
use GFP_PGTABLE_KERNEL, which may sleep unless such scope restrictions are
applied. For example:

<snip>
__pte_alloc_kernel()
pte_alloc_one_kernel(&init_mm);
pagetable_alloc_noprof(GFP_PGTABLE_KERNEL & ~__GFP_HIGHMEM, 0);
<snip>

Note: in most cases, PTE entries are established only up to the level
required by current vmap space usage, meaning the page tables are
typically fully populated during the mapping process.

Link: https://lkml.kernel.org/r/20251007122035.56347-6-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
8da89ba1 9c477531

+44 -10
+2
include/linux/vmalloc.h
··· 332 332 static inline bool vmalloc_dump_obj(void *object) { return false; } 333 333 #endif 334 334 335 + unsigned int memalloc_apply_gfp_scope(gfp_t gfp_mask); 336 + void memalloc_restore_scope(unsigned int flags); 335 337 #endif /* _LINUX_VMALLOC_H */
+42 -10
mm/vmalloc.c
··· 3716 3716 schedule_work(&cleanup_vm_area); 3717 3717 } 3718 3718 3719 + /* 3720 + * Page tables allocations ignore external GFP. Enforces it by 3721 + * the memalloc scope API. It is used by vmalloc internals and 3722 + * KASAN shadow population only. 3723 + * 3724 + * GFP to scope mapping: 3725 + * 3726 + * non-blocking (no __GFP_DIRECT_RECLAIM) - memalloc_noreclaim_save() 3727 + * GFP_NOFS - memalloc_nofs_save() 3728 + * GFP_NOIO - memalloc_noio_save() 3729 + * 3730 + * Returns a flag cookie to pair with restore. 3731 + */ 3732 + unsigned int 3733 + memalloc_apply_gfp_scope(gfp_t gfp_mask) 3734 + { 3735 + unsigned int flags = 0; 3736 + 3737 + if (!gfpflags_allow_blocking(gfp_mask)) 3738 + flags = memalloc_noreclaim_save(); 3739 + else if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO) 3740 + flags = memalloc_nofs_save(); 3741 + else if ((gfp_mask & (__GFP_FS | __GFP_IO)) == 0) 3742 + flags = memalloc_noio_save(); 3743 + 3744 + /* 0 - no scope applied. */ 3745 + return flags; 3746 + } 3747 + 3748 + void 3749 + memalloc_restore_scope(unsigned int flags) 3750 + { 3751 + if (flags) 3752 + memalloc_flags_restore(flags); 3753 + } 3754 + 3719 3755 static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, 3720 3756 pgprot_t prot, unsigned int page_shift, 3721 3757 int node) ··· 3767 3731 int ret; 3768 3732 3769 3733 array_size = (unsigned long)nr_small_pages * sizeof(struct page *); 3734 + 3735 + /* __GFP_NOFAIL and "noblock" flags are mutually exclusive. */ 3736 + if (!gfpflags_allow_blocking(gfp_mask)) 3737 + nofail = false; 3770 3738 3771 3739 if (!(gfp_mask & (GFP_DMA | GFP_DMA32))) 3772 3740 gfp_mask |= __GFP_HIGHMEM; ··· 3837 3797 * page tables allocations ignore external gfp mask, enforce it 3838 3798 * by the scope API 3839 3799 */ 3840 - if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO) 3841 - flags = memalloc_nofs_save(); 3842 - else if ((gfp_mask & (__GFP_FS | __GFP_IO)) == 0) 3843 - flags = memalloc_noio_save(); 3844 - 3800 + flags = memalloc_apply_gfp_scope(gfp_mask); 3845 3801 do { 3846 3802 ret = vmap_pages_range(addr, addr + size, prot, area->pages, 3847 3803 page_shift); 3848 3804 if (nofail && (ret < 0)) 3849 3805 schedule_timeout_uninterruptible(1); 3850 3806 } while (nofail && (ret < 0)); 3851 - 3852 - if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO) 3853 - memalloc_nofs_restore(flags); 3854 - else if ((gfp_mask & (__GFP_FS | __GFP_IO)) == 0) 3855 - memalloc_noio_restore(flags); 3807 + memalloc_restore_scope(flags); 3856 3808 3857 3809 if (ret < 0) { 3858 3810 warn_alloc(gfp_mask, NULL,