mirror of https://github.com/torvalds/linux.git
kmsan: remove hard-coded GFP_KERNEL flags
kmsan_vmap_pages_range_noflush() allocates its temp s_pages/o_pages arrays with GFP_KERNEL, which may sleep. This is inconsistent with vmalloc() as it will support non-blocking requests later. Plumb gfp_mask through the kmsan_vmap_pages_range_noflush(), so it can use it internally for its demand. Please note, the subsequent __vmap_pages_range_noflush() still uses GFP_KERNEL and can sleep. If a caller runs under reclaim constraints, sleeping is forbidden, it must establish the appropriate memalloc scope API. Link: https://lkml.kernel.org/r/20251007122035.56347-8-urezki@gmail.com Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com> Reviewed-by: Alexander Potapenko <glider@google.com> Cc: Marco Elver <elver@google.com> Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com> Cc: Baoquan He <bhe@redhat.com> Cc: Michal Hocko <mhocko@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
ad435e79f8
commit
b186a94227
|
|
@ -133,6 +133,7 @@ void kmsan_kfree_large(const void *ptr);
|
|||
* @prot: page protection flags used for vmap.
|
||||
* @pages: array of pages.
|
||||
* @page_shift: page_shift passed to vmap_range_noflush().
|
||||
* @gfp_mask: gfp_mask to use internally.
|
||||
*
|
||||
* KMSAN maps shadow and origin pages of @pages into contiguous ranges in
|
||||
* vmalloc metadata address range. Returns 0 on success, callers must check
|
||||
|
|
@ -142,7 +143,8 @@ int __must_check kmsan_vmap_pages_range_noflush(unsigned long start,
|
|||
unsigned long end,
|
||||
pgprot_t prot,
|
||||
struct page **pages,
|
||||
unsigned int page_shift);
|
||||
unsigned int page_shift,
|
||||
gfp_t gfp_mask);
|
||||
|
||||
/**
|
||||
* kmsan_vunmap_kernel_range_noflush() - Notify KMSAN about a vunmap.
|
||||
|
|
@ -347,7 +349,7 @@ static inline void kmsan_kfree_large(const void *ptr)
|
|||
|
||||
static inline int __must_check kmsan_vmap_pages_range_noflush(
|
||||
unsigned long start, unsigned long end, pgprot_t prot,
|
||||
struct page **pages, unsigned int page_shift)
|
||||
struct page **pages, unsigned int page_shift, gfp_t gfp_mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1355,7 +1355,7 @@ size_t splice_folio_into_pipe(struct pipe_inode_info *pipe,
|
|||
#ifdef CONFIG_MMU
|
||||
void __init vmalloc_init(void);
|
||||
int __must_check vmap_pages_range_noflush(unsigned long addr, unsigned long end,
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift);
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift, gfp_t gfp_mask);
|
||||
unsigned int get_vm_area_page_order(struct vm_struct *vm);
|
||||
#else
|
||||
static inline void vmalloc_init(void)
|
||||
|
|
@ -1364,7 +1364,7 @@ static inline void vmalloc_init(void)
|
|||
|
||||
static inline
|
||||
int __must_check vmap_pages_range_noflush(unsigned long addr, unsigned long end,
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift)
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift, gfp_t gfp_mask)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ void kmsan_free_page(struct page *page, unsigned int order)
|
|||
|
||||
int kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
|
||||
pgprot_t prot, struct page **pages,
|
||||
unsigned int page_shift)
|
||||
unsigned int page_shift, gfp_t gfp_mask)
|
||||
{
|
||||
unsigned long shadow_start, origin_start, shadow_end, origin_end;
|
||||
struct page **s_pages, **o_pages;
|
||||
|
|
@ -230,8 +230,8 @@ int kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
|
|||
return 0;
|
||||
|
||||
nr = (end - start) / PAGE_SIZE;
|
||||
s_pages = kcalloc(nr, sizeof(*s_pages), GFP_KERNEL);
|
||||
o_pages = kcalloc(nr, sizeof(*o_pages), GFP_KERNEL);
|
||||
s_pages = kcalloc(nr, sizeof(*s_pages), gfp_mask);
|
||||
o_pages = kcalloc(nr, sizeof(*o_pages), gfp_mask);
|
||||
if (!s_pages || !o_pages) {
|
||||
err = -ENOMEM;
|
||||
goto ret;
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ static int __pcpu_map_pages(unsigned long addr, struct page **pages,
|
|||
int nr_pages)
|
||||
{
|
||||
return vmap_pages_range_noflush(addr, addr + (nr_pages << PAGE_SHIFT),
|
||||
PAGE_KERNEL, pages, PAGE_SHIFT);
|
||||
PAGE_KERNEL, pages, PAGE_SHIFT, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
26
mm/vmalloc.c
26
mm/vmalloc.c
|
|
@ -671,16 +671,28 @@ int __vmap_pages_range_noflush(unsigned long addr, unsigned long end,
|
|||
}
|
||||
|
||||
int vmap_pages_range_noflush(unsigned long addr, unsigned long end,
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift)
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
int ret = kmsan_vmap_pages_range_noflush(addr, end, prot, pages,
|
||||
page_shift);
|
||||
page_shift, gfp_mask);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
return __vmap_pages_range_noflush(addr, end, prot, pages, page_shift);
|
||||
}
|
||||
|
||||
static int __vmap_pages_range(unsigned long addr, unsigned long end,
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = vmap_pages_range_noflush(addr, end, prot, pages, page_shift, gfp_mask);
|
||||
flush_cache_vmap(addr, end);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* vmap_pages_range - map pages to a kernel virtual address
|
||||
* @addr: start of the VM area to map
|
||||
|
|
@ -696,11 +708,7 @@ int vmap_pages_range_noflush(unsigned long addr, unsigned long end,
|
|||
int vmap_pages_range(unsigned long addr, unsigned long end,
|
||||
pgprot_t prot, struct page **pages, unsigned int page_shift)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = vmap_pages_range_noflush(addr, end, prot, pages, page_shift);
|
||||
flush_cache_vmap(addr, end);
|
||||
return err;
|
||||
return __vmap_pages_range(addr, end, prot, pages, page_shift, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static int check_sparse_vm_area(struct vm_struct *area, unsigned long start,
|
||||
|
|
@ -3839,8 +3847,8 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
|
|||
*/
|
||||
flags = memalloc_apply_gfp_scope(gfp_mask);
|
||||
do {
|
||||
ret = vmap_pages_range(addr, addr + size, prot, area->pages,
|
||||
page_shift);
|
||||
ret = __vmap_pages_range(addr, addr + size, prot, area->pages,
|
||||
page_shift, nested_gfp);
|
||||
if (nofail && (ret < 0))
|
||||
schedule_timeout_uninterruptible(1);
|
||||
} while (nofail && (ret < 0));
|
||||
|
|
|
|||
Loading…
Reference in New Issue