summaryrefslogtreecommitdiff
path: root/mm/vmalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r--mm/vmalloc.c302
1 files changed, 203 insertions, 99 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 61caa55a4402..bea9f76ed7e7 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -43,12 +43,14 @@
#include <asm/tlbflush.h>
#include <asm/shmparam.h>
#include <linux/page_owner.h>
+#include <linux/cleanup.h>
#define CREATE_TRACE_POINTS
#include <trace/events/vmalloc.h>
#include "internal.h"
#include "pgalloc-track.h"
+#include "vmalloc.h"
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
static unsigned int __ro_after_init ioremap_max_page_shift = BITS_PER_LONG - 1;
@@ -158,10 +160,21 @@ static int vmap_try_huge_pmd(pmd_t *pmd, unsigned long addr, unsigned long end,
if (!IS_ALIGNED(phys_addr, PMD_SIZE))
return 0;
- if (pmd_present(*pmd) && !pmd_free_pte_page(pmd, addr))
- return 0;
+ if (!pmd_present(*pmd))
+ return pmd_set_huge(pmd, phys_addr, prot);
- return pmd_set_huge(pmd, phys_addr, prot);
+ /*
+ * Acquire the mmap read lock to exclude ptdump, which walks
+ * kernel page tables it does not own under the mmap write lock.
+ *
+ * Concurrent read lock holders are safe: each exclusively owns
+ * the range it operates on and cannot reach this page table.
+ */
+ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm) {
+ if (!pmd_free_pte_page(pmd, addr))
+ return 0;
+ return pmd_set_huge(pmd, phys_addr, prot);
+ }
}
static int vmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
@@ -210,10 +223,15 @@ static int vmap_try_huge_pud(pud_t *pud, unsigned long addr, unsigned long end,
if (!IS_ALIGNED(phys_addr, PUD_SIZE))
return 0;
- if (pud_present(*pud) && !pud_free_pmd_page(pud, addr))
- return 0;
+ if (!pud_present(*pud))
+ return pud_set_huge(pud, phys_addr, prot);
- return pud_set_huge(pud, phys_addr, prot);
+ /* See comment in vmap_try_huge_pmd(). */
+ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm) {
+ if (!pud_free_pmd_page(pud, addr))
+ return 0;
+ return pud_set_huge(pud, phys_addr, prot);
+ }
}
static int vmap_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
@@ -262,10 +280,15 @@ static int vmap_try_huge_p4d(p4d_t *p4d, unsigned long addr, unsigned long end,
if (!IS_ALIGNED(phys_addr, P4D_SIZE))
return 0;
- if (p4d_present(*p4d) && !p4d_free_pud_page(p4d, addr))
- return 0;
+ if (!p4d_present(*p4d))
+ return p4d_set_huge(p4d, phys_addr, prot);
- return p4d_set_huge(p4d, phys_addr, prot);
+ /* See comment in vmap_try_huge_pmd(). */
+ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm) {
+ if (!p4d_free_pud_page(p4d, addr))
+ return 0;
+ return p4d_set_huge(p4d, phys_addr, prot);
+ }
}
static int vmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end,
@@ -1068,14 +1091,8 @@ static BLOCKING_NOTIFIER_HEAD(vmap_notify_list);
static void drain_vmap_area_work(struct work_struct *work);
static DECLARE_WORK(drain_vmap_work, drain_vmap_area_work);
-static __cacheline_aligned_in_smp atomic_long_t nr_vmalloc_pages;
static __cacheline_aligned_in_smp atomic_long_t vmap_lazy_nr;
-unsigned long vmalloc_nr_pages(void)
-{
- return atomic_long_read(&nr_vmalloc_pages);
-}
-
static struct vmap_area *__find_vmap_area(unsigned long addr, struct rb_root *root)
{
struct rb_node *n = root->rb_node;
@@ -1823,8 +1840,10 @@ va_alloc(struct vmap_area *va,
/* Update the free vmap_area. */
ret = va_clip(root, head, va, nva_start_addr, size);
- if (WARN_ON_ONCE(ret))
+ if (ret) {
+ WARN_ON_ONCE(ret != -ENOMEM);
return ret;
+ }
return nva_start_addr;
}
@@ -1897,12 +1916,9 @@ preload_this_cpu_lock(spinlock_t *lock, gfp_t gfp_mask, int node)
/*
* Preload this CPU with one extra vmap_area object. It is used
- * when fit type of free area is NE_FIT_TYPE. It guarantees that
- * a CPU that does an allocation is preloaded.
- *
- * We do it in non-atomic context, thus it allows us to use more
- * permissive allocation masks to be more stable under low memory
- * condition and high memory pressure.
+ * when fit type of free area is NE_FIT_TYPE. It is best effort
+ * pre-loading. If it fails va_clip() may return -ENOMEM from its
+ * GFP_NOWAIT fallback.
*/
if (!this_cpu_read(ne_fit_preload_node))
va = kmem_cache_alloc_node(vmap_area_cachep, gfp_mask, node);
@@ -3189,7 +3205,7 @@ void __init vm_area_register_early(struct vm_struct *vm, size_t align)
kasan_populate_early_vm_area_shadow(vm->addr, vm->size);
}
-static void clear_vm_uninitialized_flag(struct vm_struct *vm)
+void clear_vm_uninitialized_flag(struct vm_struct *vm)
{
/*
* Before removing VM_UNINITIALIZED,
@@ -3209,7 +3225,7 @@ struct vm_struct *__get_vm_area_node(unsigned long size,
struct vm_struct *area;
unsigned long requested_size = size;
- BUG_ON(in_interrupt());
+ BUG_ON(in_nmi() || in_hardirq());
size = ALIGN(size, 1ul << shift);
if (unlikely(!size))
return NULL;
@@ -3344,7 +3360,7 @@ struct vm_struct *remove_vm_area(const void *addr)
static inline void set_area_direct_map(const struct vm_struct *area,
int (*set_direct_map)(struct page *page))
{
- int i;
+ unsigned long i;
/* HUGE_VMALLOC passes small pages to set_direct_map */
for (i = 0; i < area->nr_pages; i++)
@@ -3360,7 +3376,7 @@ static void vm_reset_perms(struct vm_struct *area)
unsigned long start = ULONG_MAX, end = 0;
unsigned int page_order = vm_area_page_order(area);
int flush_dmap = 0;
- int i;
+ unsigned long i;
/*
* Find the start and end range of the direct mappings to make sure that
@@ -3422,6 +3438,32 @@ void vfree_atomic(const void *addr)
schedule_work(&p->wq);
}
+/*
+ * vm_area_free_pages - free a range of pages from a vmalloc allocation
+ * @vm: the vm_struct containing the pages
+ * @start_idx: first page index to free (inclusive)
+ * @end_idx: last page index to free (exclusive)
+ *
+ * Free pages [start_idx, end_idx) updating NR_VMALLOC stat accounting.
+ * Freed vm->pages[] entries are set to NULL.
+ * Caller is responsible for unmapping (vunmap_range) and KASAN
+ * poisoning before calling this.
+ */
+static void vm_area_free_pages(struct vm_struct *vm, unsigned long start_idx,
+ unsigned long end_idx)
+{
+ unsigned long i;
+
+ if (!(vm->flags & VM_MAP_PUT_PAGES)) {
+ for (i = start_idx; i < end_idx; i++)
+ mod_lruvec_page_state(vm->pages[i], NR_VMALLOC, -1);
+ }
+ free_pages_bulk(vm->pages + start_idx, end_idx - start_idx);
+
+ for (i = start_idx; i < end_idx; i++)
+ vm->pages[i] = NULL;
+}
+
/**
* vfree - Release memory allocated by vmalloc()
* @addr: Memory base address
@@ -3442,7 +3484,6 @@ void vfree_atomic(const void *addr)
void vfree(const void *addr)
{
struct vm_struct *vm;
- int i;
if (unlikely(in_interrupt())) {
vfree_atomic(addr);
@@ -3465,22 +3506,8 @@ void vfree(const void *addr)
if (unlikely(vm->flags & VM_FLUSH_RESET_PERMS))
vm_reset_perms(vm);
- /* All pages of vm should be charged to same memcg, so use first one. */
- if (vm->nr_pages && !(vm->flags & VM_MAP_PUT_PAGES))
- mod_memcg_page_state(vm->pages[0], MEMCG_VMALLOC, -vm->nr_pages);
- for (i = 0; i < vm->nr_pages; i++) {
- struct page *page = vm->pages[i];
- BUG_ON(!page);
- /*
- * High-order allocs for huge vmallocs are split, so
- * can be freed as an array of order-0 allocations
- */
- __free_page(page);
- cond_resched();
- }
- if (!(vm->flags & VM_MAP_PUT_PAGES))
- atomic_long_sub(vm->nr_pages, &nr_vmalloc_pages);
+ vm_area_free_pages(vm, 0, vm->nr_pages);
kvfree(vm->pages);
kfree(vm);
}
@@ -3637,12 +3664,12 @@ static inline gfp_t vmalloc_gfp_adjust(gfp_t flags, const bool large)
return flags;
}
-static inline unsigned int
+static inline unsigned long
vm_area_alloc_pages(gfp_t gfp, int nid,
- unsigned int order, unsigned int nr_pages, struct page **pages)
+ unsigned int order, unsigned long nr_pages, struct page **pages)
{
- unsigned int nr_allocated = 0;
- unsigned int nr_remaining = nr_pages;
+ unsigned long nr_allocated = 0;
+ unsigned long nr_remaining = nr_pages;
unsigned int max_attempt_order = MAX_PAGE_ORDER;
struct page *page;
int i;
@@ -3668,6 +3695,8 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
continue;
}
+ mod_lruvec_page_state(page, NR_VMALLOC, 1 << large_order);
+
split_page(page, large_order);
for (i = 0; i < (1U << large_order); i++)
pages[nr_allocated + i] = page + i;
@@ -3688,6 +3717,7 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
if (!order) {
while (nr_allocated < nr_pages) {
unsigned int nr, nr_pages_request;
+ unsigned long i;
/*
* A maximum allowed request is hard-coded and is 100
@@ -3695,7 +3725,7 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
* long preemption off scenario in the bulk-allocator
* so the range is [1:100].
*/
- nr_pages_request = min(100U, nr_pages - nr_allocated);
+ nr_pages_request = min(100UL, nr_pages - nr_allocated);
/* memory allocation should consider mempolicy, we can't
* wrongly use nearest node when nid == NUMA_NO_NODE,
@@ -3711,6 +3741,9 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
nr_pages_request,
pages + nr_allocated);
+ for (i = nr_allocated; i < nr_allocated + nr; i++)
+ mod_lruvec_page_state(pages[i], NR_VMALLOC, 1);
+
nr_allocated += nr;
/*
@@ -3735,6 +3768,8 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
if (unlikely(!page))
break;
+ mod_lruvec_page_state(page, NR_VMALLOC, 1 << order);
+
/*
* High-order allocations must be able to be treated as
* independent small pages by callers (as they can with
@@ -3798,6 +3833,8 @@ static void defer_vm_area_cleanup(struct vm_struct *area)
* non-blocking (no __GFP_DIRECT_RECLAIM) - memalloc_noreclaim_save()
* GFP_NOFS - memalloc_nofs_save()
* GFP_NOIO - memalloc_noio_save()
+ * __GFP_RETRY_MAYFAIL, __GFP_NORETRY - memalloc_noreclaim_save()
+ * to prevent OOMs
*
* Returns a flag cookie to pair with restore.
*/
@@ -3806,7 +3843,8 @@ memalloc_apply_gfp_scope(gfp_t gfp_mask)
{
unsigned int flags = 0;
- if (!gfpflags_allow_blocking(gfp_mask))
+ if (!gfpflags_allow_blocking(gfp_mask) ||
+ (gfp_mask & (__GFP_RETRY_MAYFAIL | __GFP_NORETRY)))
flags = memalloc_noreclaim_save();
else if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO)
flags = memalloc_nofs_save();
@@ -3833,12 +3871,12 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
unsigned long addr = (unsigned long)area->addr;
unsigned long size = get_vm_area_size(area);
unsigned long array_size;
- unsigned int nr_small_pages = size >> PAGE_SHIFT;
+ unsigned long nr_small_pages = size >> PAGE_SHIFT;
unsigned int page_order;
unsigned int flags;
int ret;
- array_size = (unsigned long)nr_small_pages * sizeof(struct page *);
+ array_size = nr_small_pages * sizeof(struct page *);
/* __GFP_NOFAIL and "noblock" flags are mutually exclusive. */
if (!gfpflags_allow_blocking(gfp_mask))
@@ -3877,12 +3915,6 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
vmalloc_gfp_adjust(gfp_mask, page_order), node,
page_order, nr_small_pages, area->pages);
- atomic_long_add(area->nr_pages, &nr_vmalloc_pages);
- /* All pages of vm should be charged to same memcg, so use first one. */
- if (gfp_mask & __GFP_ACCOUNT && area->nr_pages)
- mod_memcg_page_state(area->pages[0], MEMCG_VMALLOC,
- area->nr_pages);
-
/*
* If not enough pages were obtained to accomplish an
* allocation request, free them via vfree() if any.
@@ -3901,7 +3933,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
if (!fatal_signal_pending(current) && page_order == 0)
warn_alloc(gfp_mask, NULL,
"vmalloc error: size %lu, failed to allocate pages",
- area->nr_pages * PAGE_SIZE);
+ nr_small_pages * PAGE_SIZE);
goto fail;
}
@@ -3940,9 +3972,10 @@ fail:
* GFP_KERNEL_ACCOUNT. Xfs uses __GFP_NOLOCKDEP.
*/
#define GFP_VMALLOC_SUPPORTED (GFP_KERNEL | GFP_ATOMIC | GFP_NOWAIT |\
- __GFP_NOFAIL | __GFP_ZERO | __GFP_NORETRY |\
+ __GFP_NOFAIL | __GFP_ZERO |\
+ __GFP_NORETRY | __GFP_RETRY_MAYFAIL |\
GFP_NOFS | GFP_NOIO | GFP_KERNEL_ACCOUNT |\
- GFP_USER | __GFP_NOLOCKDEP)
+ GFP_USER | __GFP_NOLOCKDEP | __GFP_SKIP_KASAN)
static gfp_t vmalloc_fix_flags(gfp_t flags)
{
@@ -3971,15 +4004,21 @@ static gfp_t vmalloc_fix_flags(gfp_t flags)
* virtual range with protection @prot.
*
* Supported GFP classes: %GFP_KERNEL, %GFP_ATOMIC, %GFP_NOWAIT,
- * %GFP_NOFS and %GFP_NOIO. Zone modifiers are not supported.
+ * %__GFP_RETRY_MAYFAIL, %__GFP_NORETRY, %GFP_NOFS and %GFP_NOIO.
+ * Zone modifiers are not supported.
* Please note %GFP_ATOMIC and %GFP_NOWAIT are supported only
* by __vmalloc().
*
- * Retry modifiers: only %__GFP_NOFAIL is supported; %__GFP_NORETRY
- * and %__GFP_RETRY_MAYFAIL are not supported.
+ * Retry modifiers: only %__GFP_NOFAIL is fully supported;
+ * %__GFP_NORETRY and %__GFP_RETRY_MAYFAIL are supported with limitation,
+ * i.e. page tables are allocated with NOWAIT semantic so they might fail
+ * under moderate memory pressure.
*
* %__GFP_NOWARN can be used to suppress failure messages.
*
+ * %__GFP_SKIP_KASAN can be used to skip unpoisoning of mapped pages
+ * (when prot=%PAGE_KERNEL).
+ *
* Can not be called from interrupt nor NMI contexts.
* Return: the address of the area or %NULL on failure
*/
@@ -3993,6 +4032,7 @@ void *__vmalloc_node_range_noprof(unsigned long size, unsigned long align,
kasan_vmalloc_flags_t kasan_flags = KASAN_VMALLOC_NONE;
unsigned long original_align = align;
unsigned int shift = PAGE_SHIFT;
+ bool skip_vmalloc_kasan = kasan_hw_tags_enabled() && (gfp_mask & __GFP_SKIP_KASAN);
if (WARN_ON_ONCE(!size))
return NULL;
@@ -4023,12 +4063,12 @@ void *__vmalloc_node_range_noprof(unsigned long size, unsigned long align,
again:
area = __get_vm_area_node(size, align, shift, VM_ALLOC |
VM_UNINITIALIZED | vm_flags, start, end, node,
- gfp_mask, caller);
+ gfp_mask & ~__GFP_SKIP_KASAN, caller);
if (!area) {
bool nofail = gfp_mask & __GFP_NOFAIL;
warn_alloc(gfp_mask, NULL,
- "vmalloc error: size %lu, vm_struct allocation failed%s",
- size, (nofail) ? ". Retrying." : "");
+ "vmalloc error: size %lu, align 0x%lx, vm_struct allocation failed%s",
+ size, align, (nofail) ? ". Retrying." : "");
if (nofail) {
schedule_timeout_uninterruptible(1);
goto again;
@@ -4041,7 +4081,7 @@ again:
* kasan_unpoison_vmalloc().
*/
if (pgprot_val(prot) == pgprot_val(PAGE_KERNEL)) {
- if (kasan_hw_tags_enabled()) {
+ if (kasan_hw_tags_enabled() && !skip_vmalloc_kasan) {
/*
* Modify protection bits to allow tagging.
* This must be done before mapping.
@@ -4078,7 +4118,8 @@ again:
(gfp_mask & __GFP_SKIP_ZERO))
kasan_flags |= KASAN_VMALLOC_INIT;
/* KASAN_VMALLOC_PROT_NORMAL already set if required. */
- area->addr = kasan_unpoison_vmalloc(area->addr, size, kasan_flags);
+ if (!skip_vmalloc_kasan)
+ area->addr = kasan_unpoison_vmalloc(area->addr, size, kasan_flags);
/*
* In this function, newly allocated vm_struct has VM_UNINITIALIZED
@@ -4324,16 +4365,67 @@ void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long align
if (unlikely(flags & __GFP_THISNODE) && nid != NUMA_NO_NODE &&
nid != page_to_nid(vmalloc_to_page(p)))
goto need_realloc;
+ } else {
+ /*
+ * If p is NULL, vrealloc behaves exactly like vmalloc.
+ * Skip the shrink and in-place grow paths.
+ */
+ goto need_realloc;
}
- /*
- * TODO: Shrink the vm_area, i.e. unmap and free unused pages. What
- * would be a good heuristic for when to shrink the vm_area?
- */
if (size <= old_size) {
+ unsigned long new_nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
/* Zero out "freed" memory, potentially for future realloc. */
if (want_init_on_free() || want_init_on_alloc(flags))
memset((void *)p + size, 0, old_size - size);
+
+ /*
+ * Free tail pages when shrink crosses a page boundary.
+ *
+ * Skip huge page allocations (page_order > 0) as partial
+ * freeing would require splitting.
+ *
+ * Skip VM_FLUSH_RESET_PERMS, as direct-map permissions must
+ * be reset before pages are returned to the allocator.
+ *
+ * Skip VM_USERMAP, as remap_vmalloc_range_partial() validates
+ * mapping requests against the unchanged vm->size; freeing
+ * tail pages would cause vmalloc_to_page() to return NULL for
+ * the unmapped range.
+ *
+ * Skip if either GFP_NOFS or GFP_NOIO are used.
+ * kmemleak_free_part() internally allocates with
+ * GFP_KERNEL, which could trigger a recursive deadlock
+ * if we are under filesystem or I/O reclaim.
+ */
+ if (new_nr_pages < vm->nr_pages && !vm_area_page_order(vm) &&
+ !(vm->flags & (VM_FLUSH_RESET_PERMS | VM_USERMAP)) &&
+ gfp_has_io_fs(flags)) {
+ unsigned long addr = (unsigned long)kasan_reset_tag(p);
+ unsigned long old_nr_pages = vm->nr_pages;
+
+ /*
+ * Use the node lock to synchronize with concurrent
+ * readers (vmalloc_info_show).
+ */
+ struct vmap_node *vn = addr_to_node(addr);
+
+ spin_lock(&vn->busy.lock);
+ vm->nr_pages = new_nr_pages;
+ spin_unlock(&vn->busy.lock);
+
+ /* Notify kmemleak of the reduced allocation size before unmapping. */
+ kmemleak_free_part((void *)addr +
+ (new_nr_pages << PAGE_SHIFT),
+ (old_nr_pages - new_nr_pages)
+ << PAGE_SHIFT);
+
+ vunmap_range(addr + (new_nr_pages << PAGE_SHIFT),
+ addr + (old_nr_pages << PAGE_SHIFT));
+
+ vm_area_free_pages(vm, new_nr_pages, old_nr_pages);
+ }
vm->requested_size = size;
kasan_vrealloc(p, old_size, size);
return (void *)p;
@@ -4342,7 +4434,7 @@ void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long align
/*
* We already have the bytes available in the allocation; use them.
*/
- if (size <= alloced_size) {
+ if (size <= vm->nr_pages << PAGE_SHIFT) {
/*
* No need to zero memory here, as unused memory will have
* already been zeroed at initial allocation time or during
@@ -4361,7 +4453,7 @@ need_realloc:
return NULL;
if (p) {
- memcpy(n, p, old_size);
+ memcpy(n, p, min(size, old_size));
vfree(p);
}
@@ -4575,20 +4667,20 @@ finished:
* @count: number of bytes to be read.
*
* This function checks that addr is a valid vmalloc'ed area, and
- * copy data from that area to a given buffer. If the given memory range
+ * copies data from that area to a given iterator. If the given memory range
* of [addr...addr+count) includes some valid address, data is copied to
- * proper area of @buf. If there are memory holes, they'll be zero-filled.
+ * proper area of @iter. If there are memory holes, they'll be zero-filled.
* IOREMAP area is treated as memory hole and no copy is done.
*
* If [addr...addr+count) doesn't includes any intersects with alive
- * vm_struct area, returns 0. @buf should be kernel's buffer.
+ * vm_struct area, returns 0.
*
- * Note: In usual ops, vread() is never necessary because the caller
+ * Note: In usual ops, vread_iter() is never necessary because the caller
* should know vmalloc() area is valid and can use memcpy().
* This is for routines which have to access vmalloc area without
* any information, as /proc/kcore.
*
- * Return: number of bytes for which addr and buf should be increased
+ * Return: number of bytes for which addr and iter should be advanced
* (same number as @count) or %0 if [addr...addr+count) doesn't
* include any intersection with valid vmalloc area
*/
@@ -4641,7 +4733,18 @@ long vread_iter(struct iov_iter *iter, const char *addr, size_t count)
smp_rmb();
vaddr = (char *) va->va_start;
- size = vm ? get_vm_area_size(vm) : va_size(va);
+ if (vm)
+ /*
+ * For VM_ALLOC areas, use nr_pages rather than
+ * get_vm_area_size() because vrealloc() may shrink
+ * the mapping without updating area->size. Other
+ * mapping types (vmap, ioremap) don't set nr_pages.
+ */
+ size = (vm->flags & VM_ALLOC && vm->nr_pages) ?
+ (vm->nr_pages << PAGE_SHIFT) :
+ get_vm_area_size(vm);
+ else
+ size = va_size(va);
if (addr >= vaddr + size)
goto next_va;
@@ -4862,16 +4965,17 @@ pvm_determine_end_from_reverse(struct vmap_area **va, unsigned long align)
* @sizes: array containing size of each area
* @nr_vms: the number of areas to allocate
* @align: alignment, all entries in @offsets and @sizes must be aligned to this
+ * @gfp: allocation flags passed to the underlying memory allocator
*
* Returns: kmalloc'd vm_struct pointer array pointing to allocated
* vm_structs on success, %NULL on failure
*
* Percpu allocator wants to use congruent vm areas so that it can
* maintain the offsets among percpu areas. This function allocates
- * congruent vmalloc areas for it with GFP_KERNEL. These areas tend to
- * be scattered pretty far, distance between two areas easily going up
- * to gigabytes. To avoid interacting with regular vmallocs, these
- * areas are allocated from top.
+ * congruent vmalloc areas for it. These areas tend to be scattered
+ * pretty far, distance between two areas easily going up to gigabytes.
+ * To avoid interacting with regular vmallocs, these areas are allocated
+ * from top.
*
* Despite its complicated look, this allocator is rather simple. It
* does everything top-down and scans free blocks from the end looking
@@ -4882,7 +4986,7 @@ pvm_determine_end_from_reverse(struct vmap_area **va, unsigned long align)
*/
struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
const size_t *sizes, int nr_vms,
- size_t align)
+ size_t align, gfp_t gfp)
{
const unsigned long vmalloc_start = ALIGN(VMALLOC_START, align);
const unsigned long vmalloc_end = VMALLOC_END & ~(align - 1);
@@ -4920,14 +5024,14 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
return NULL;
}
- vms = kzalloc_objs(vms[0], nr_vms);
- vas = kzalloc_objs(vas[0], nr_vms);
+ vms = kzalloc_objs(vms[0], nr_vms, gfp);
+ vas = kzalloc_objs(vas[0], nr_vms, gfp);
if (!vas || !vms)
goto err_free2;
for (area = 0; area < nr_vms; area++) {
- vas[area] = kmem_cache_zalloc(vmap_area_cachep, GFP_KERNEL);
- vms[area] = kzalloc_obj(struct vm_struct);
+ vas[area] = kmem_cache_zalloc(vmap_area_cachep, gfp);
+ vms[area] = kzalloc_obj(struct vm_struct, gfp);
if (!vas[area] || !vms[area])
goto err_free;
}
@@ -5017,7 +5121,7 @@ retry:
/* populate the kasan shadow space */
for (area = 0; area < nr_vms; area++) {
- if (kasan_populate_vmalloc(vas[area]->va_start, sizes[area], GFP_KERNEL))
+ if (kasan_populate_vmalloc(vas[area]->va_start, sizes[area], gfp))
goto err_free_shadow;
}
@@ -5074,7 +5178,7 @@ overflow:
continue;
vas[area] = kmem_cache_zalloc(
- vmap_area_cachep, GFP_KERNEL);
+ vmap_area_cachep, gfp);
if (!vas[area])
goto err_free;
}
@@ -5114,9 +5218,7 @@ err_free_shadow:
kfree(vms[area]);
}
spin_unlock(&free_vmap_area_lock);
- kfree(vas);
- kfree(vms);
- return NULL;
+ goto err_free2;
}
/**
@@ -5144,7 +5246,7 @@ bool vmalloc_dump_obj(void *object)
struct vmap_area *va;
struct vmap_node *vn;
unsigned long addr;
- unsigned int nr_pages;
+ unsigned long nr_pages;
addr = PAGE_ALIGN((unsigned long) object);
vn = addr_to_node(addr);
@@ -5164,7 +5266,7 @@ bool vmalloc_dump_obj(void *object)
nr_pages = vm->nr_pages;
spin_unlock(&vn->busy.lock);
- pr_cont(" %u-page vmalloc region starting at %#lx allocated at %pS\n",
+ pr_cont(" %lu-page vmalloc region starting at %#lx allocated at %pS\n",
nr_pages, addr, caller);
return true;
@@ -5182,16 +5284,17 @@ bool vmalloc_dump_obj(void *object)
static void show_numa_info(struct seq_file *m, struct vm_struct *v,
unsigned int *counters)
{
- unsigned int nr;
unsigned int step = 1U << vm_area_page_order(v);
+ unsigned long i;
+ unsigned int nr;
if (!counters)
return;
memset(counters, 0, nr_node_ids * sizeof(unsigned int));
- for (nr = 0; nr < v->nr_pages; nr += step)
- counters[page_to_nid(v->pages[nr])] += step;
+ for (i = 0; i < v->nr_pages; i += step)
+ counters[page_to_nid(v->pages[i])] += step;
for_each_node_state(nr, N_HIGH_MEMORY)
if (counters[nr])
seq_printf(m, " N%u=%u", nr, counters[nr]);
@@ -5249,7 +5352,7 @@ static int vmalloc_info_show(struct seq_file *m, void *p)
seq_printf(m, " %pS", v->caller);
if (v->nr_pages)
- seq_printf(m, " pages=%d", v->nr_pages);
+ seq_printf(m, " pages=%lu", v->nr_pages);
if (v->phys_addr)
seq_printf(m, " phys=%pa", &v->phys_addr);
@@ -5416,6 +5519,7 @@ vmap_node_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
{
struct vmap_node *vn;
+ guard(mutex)(&vmap_purge_lock);
for_each_vmap_node(vn)
decay_va_pool_node(vn, true);