mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-27 11:46:46 -04:00
mm: replace __GFP_NO_CODETAG with ALLOC_NO_CODETAG
Now that alloc_pages has an entrypoint that allows passing alloc_flags, we can take advantage of this to start removing GFP flags that are only used for mm-internal stuff. This requires also plumbing the alloc_flags into some more of the allocator code, in particular __alloc_pages[_noprof]() gets an alloc_flags arg to go along with its callees, and we now need to pass those flags deeper into the allocator so they can reach the alloc_tag code. While moving the flag definition into page_alloc.h, also update the comment per Hao's suggestion. No functional change intended. Link: https://lore.kernel.org/all/b4916118-3537-4e19-8bc8-1d103dd0d225@linux.dev/ Link: https://lore.kernel.org/20260703-alloc-trylock-v5-15-c87b714e19d3@google.com Signed-off-by: Brendan Jackman <jackmanb@google.com> Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org> Tested-by: Hao Ge <hao.ge@linux.dev> Acked-by: Hao Ge <hao.ge@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
a4f6c0f83d
commit
6372aac4d4
@@ -165,11 +165,11 @@ static inline void alloc_tag_sub_check(union codetag_ref *ref)
|
||||
{
|
||||
WARN_ONCE(ref && !ref->ct, "alloc_tag was not set\n");
|
||||
}
|
||||
void alloc_tag_add_early_pfn(unsigned long pfn, gfp_t gfp_flags);
|
||||
void alloc_tag_add_early_pfn(unsigned long pfn, unsigned int alloc_flags);
|
||||
#else
|
||||
static inline void alloc_tag_add_check(union codetag_ref *ref, struct alloc_tag *tag) {}
|
||||
static inline void alloc_tag_sub_check(union codetag_ref *ref) {}
|
||||
static inline void alloc_tag_add_early_pfn(unsigned long pfn, gfp_t gfp_flags) {}
|
||||
static inline void alloc_tag_add_early_pfn(unsigned long pfn, unsigned int alloc_flags) {}
|
||||
#endif
|
||||
|
||||
/* Caller should verify both ref and tag to be valid */
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kmemleak.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "page_alloc.h"
|
||||
|
||||
#define ALLOCINFO_FILE_NAME "allocinfo"
|
||||
#define MODULE_ALLOC_TAG_VMAP_SIZE (100000UL * sizeof(struct alloc_tag))
|
||||
#define SECTION_START(NAME) (CODETAG_SECTION_START_PREFIX NAME)
|
||||
@@ -792,19 +795,6 @@ struct pfn_pool {
|
||||
|
||||
#define PFN_POOL_SIZE ((PAGE_SIZE - offsetof(struct pfn_pool, pfns)) / \
|
||||
sizeof(unsigned long))
|
||||
|
||||
/*
|
||||
* Skip early PFN recording for a page allocation. Reuses the
|
||||
* %__GFP_NO_OBJ_EXT bit. Used by __alloc_tag_add_early_pfn() to avoid
|
||||
* recursion when allocating pages for the early PFN tracking list
|
||||
* itself.
|
||||
*
|
||||
* Codetags of the pages allocated with __GFP_NO_CODETAG should be
|
||||
* cleared (via clear_page_tag_ref()) before freeing the pages to prevent
|
||||
* alloc_tag_sub_check() from triggering a warning.
|
||||
*/
|
||||
#define __GFP_NO_CODETAG __GFP_NO_OBJ_EXT
|
||||
|
||||
static struct pfn_pool *current_pfn_pool __initdata;
|
||||
|
||||
static void __init __alloc_tag_add_early_pfn(unsigned long pfn)
|
||||
@@ -815,7 +805,8 @@ static void __init __alloc_tag_add_early_pfn(unsigned long pfn)
|
||||
do {
|
||||
pool = READ_ONCE(current_pfn_pool);
|
||||
if (!pool || atomic_read(&pool->count) >= PFN_POOL_SIZE) {
|
||||
struct page *new_page = alloc_page(__GFP_HIGH | __GFP_NO_CODETAG);
|
||||
struct page *new_page = __alloc_pages(__GFP_HIGH, 0, numa_mem_id(),
|
||||
NULL, ALLOC_NO_CODETAG);
|
||||
struct pfn_pool *new;
|
||||
|
||||
if (!new_page) {
|
||||
@@ -846,7 +837,7 @@ typedef void alloc_tag_add_func(unsigned long pfn);
|
||||
static alloc_tag_add_func __rcu *alloc_tag_add_early_pfn_ptr __refdata =
|
||||
RCU_INITIALIZER(__alloc_tag_add_early_pfn);
|
||||
|
||||
void alloc_tag_add_early_pfn(unsigned long pfn, gfp_t gfp_flags)
|
||||
void alloc_tag_add_early_pfn(unsigned long pfn, unsigned int alloc_flags)
|
||||
{
|
||||
alloc_tag_add_func *alloc_tag_add;
|
||||
|
||||
@@ -854,7 +845,7 @@ void alloc_tag_add_early_pfn(unsigned long pfn, gfp_t gfp_flags)
|
||||
return;
|
||||
|
||||
/* Skip allocations for the tracking list itself to avoid recursion. */
|
||||
if (gfp_flags & __GFP_NO_CODETAG)
|
||||
if (alloc_flags & ALLOC_NO_CODETAG)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -83,7 +83,7 @@ static inline bool is_via_compact_memory(int order) { return false; }
|
||||
|
||||
static struct page *mark_allocated_noprof(struct page *page, unsigned int order, gfp_t gfp_flags)
|
||||
{
|
||||
post_alloc_hook(page, order, __GFP_MOVABLE);
|
||||
post_alloc_hook(page, order, __GFP_MOVABLE, ALLOC_DEFAULT);
|
||||
set_page_refcounted(page);
|
||||
return page;
|
||||
}
|
||||
@@ -1851,7 +1851,7 @@ static struct folio *compaction_alloc_noprof(struct folio *src, unsigned long da
|
||||
}
|
||||
dst = (struct folio *)freepage;
|
||||
|
||||
post_alloc_hook(&dst->page, order, __GFP_MOVABLE);
|
||||
post_alloc_hook(&dst->page, order, __GFP_MOVABLE, ALLOC_DEFAULT);
|
||||
set_page_refcounted(&dst->page);
|
||||
if (order)
|
||||
prep_compound_page(&dst->page, order);
|
||||
|
||||
@@ -1249,7 +1249,7 @@ void __clear_page_tag_ref(struct page *page)
|
||||
/* Should be called only if mem_alloc_profiling_enabled() */
|
||||
static noinline
|
||||
void __pgalloc_tag_add(struct page *page, struct task_struct *task,
|
||||
unsigned int nr, gfp_t gfp_flags)
|
||||
unsigned int nr, unsigned int alloc_flags)
|
||||
{
|
||||
union pgtag_ref_handle handle;
|
||||
union codetag_ref ref;
|
||||
@@ -1263,17 +1263,17 @@ void __pgalloc_tag_add(struct page *page, struct task_struct *task,
|
||||
* page_ext is not available yet, record the pfn so we can
|
||||
* clear the tag ref later when page_ext is initialized.
|
||||
*/
|
||||
alloc_tag_add_early_pfn(page_to_pfn(page), gfp_flags);
|
||||
alloc_tag_add_early_pfn(page_to_pfn(page), alloc_flags);
|
||||
if (task->alloc_tag)
|
||||
alloc_tag_set_inaccurate(task->alloc_tag);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pgalloc_tag_add(struct page *page, struct task_struct *task,
|
||||
unsigned int nr, gfp_t gfp_flags)
|
||||
unsigned int nr, unsigned int alloc_flags)
|
||||
{
|
||||
if (mem_alloc_profiling_enabled())
|
||||
__pgalloc_tag_add(page, task, nr, gfp_flags);
|
||||
__pgalloc_tag_add(page, task, nr, alloc_flags);
|
||||
}
|
||||
|
||||
/* Should be called only if mem_alloc_profiling_enabled() */
|
||||
@@ -1306,7 +1306,7 @@ static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr)
|
||||
#else /* CONFIG_MEM_ALLOC_PROFILING */
|
||||
|
||||
static inline void pgalloc_tag_add(struct page *page, struct task_struct *task,
|
||||
unsigned int nr, gfp_t gfp_flags) {}
|
||||
unsigned int nr, unsigned int alloc_flags) {}
|
||||
static inline void pgalloc_tag_sub(struct page *page, unsigned int nr) {}
|
||||
static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr) {}
|
||||
|
||||
@@ -1810,7 +1810,7 @@ static inline bool should_skip_init(gfp_t flags)
|
||||
}
|
||||
|
||||
inline void post_alloc_hook(struct page *page, unsigned int order,
|
||||
gfp_t gfp_flags)
|
||||
gfp_t gfp_flags, unsigned int alloc_flags)
|
||||
{
|
||||
const bool zero_tags = gfp_flags & __GFP_ZEROTAGS;
|
||||
bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) &&
|
||||
@@ -1861,13 +1861,13 @@ inline void post_alloc_hook(struct page *page, unsigned int order,
|
||||
|
||||
set_page_owner(page, order, gfp_flags);
|
||||
page_table_check_alloc(page, order);
|
||||
pgalloc_tag_add(page, current, 1 << order, gfp_flags);
|
||||
pgalloc_tag_add(page, current, 1 << order, alloc_flags);
|
||||
}
|
||||
|
||||
static void prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
|
||||
unsigned int alloc_flags)
|
||||
{
|
||||
post_alloc_hook(page, order, gfp_flags);
|
||||
post_alloc_hook(page, order, gfp_flags, alloc_flags);
|
||||
|
||||
if (order && (gfp_flags & __GFP_COMP))
|
||||
prep_compound_page(page, order);
|
||||
@@ -4078,7 +4078,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
|
||||
*/
|
||||
page = get_page_from_freelist((gfp_mask | __GFP_HARDWALL) &
|
||||
~__GFP_DIRECT_RECLAIM, order,
|
||||
ALLOC_WMARK_HIGH|ALLOC_CPUSET, ac);
|
||||
ac->alloc_flags|ALLOC_WMARK_HIGH|ALLOC_CPUSET, ac);
|
||||
if (page)
|
||||
goto out;
|
||||
|
||||
@@ -4124,7 +4124,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
|
||||
*/
|
||||
if (gfp_mask & __GFP_NOFAIL)
|
||||
page = __alloc_pages_cpuset_fallback(gfp_mask, order,
|
||||
ALLOC_NO_WATERMARKS, ac);
|
||||
ac->alloc_flags|ALLOC_NO_WATERMARKS, ac);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&oom_lock);
|
||||
@@ -4791,8 +4791,12 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
|
||||
* The fast path uses conservative alloc_flags to succeed only until
|
||||
* kswapd needs to be woken up, and to avoid the cost of setting up
|
||||
* alloc_flags precisely. So we do that now.
|
||||
*
|
||||
* Can't just or alloc_flags if it contains WMARK bits, but those flags
|
||||
* shouldn't be set in ac->alloc_flags.
|
||||
*/
|
||||
alloc_flags = alloc_flags_slowpath(gfp_mask, order);
|
||||
VM_WARN_ON(ac->alloc_flags & ALLOC_WMARK_MASK);
|
||||
alloc_flags = ac->alloc_flags | alloc_flags_slowpath(gfp_mask, order);
|
||||
|
||||
/*
|
||||
* We need to recalculate the starting point for the zonelist iterator
|
||||
@@ -4834,7 +4838,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
|
||||
reserve_flags = __gfp_pfmemalloc_flags(gfp_mask);
|
||||
if (reserve_flags)
|
||||
alloc_flags = alloc_flags_cma(gfp_mask, reserve_flags) |
|
||||
(alloc_flags & ALLOC_KSWAPD);
|
||||
ac->alloc_flags | (alloc_flags & ALLOC_KSWAPD);
|
||||
|
||||
/*
|
||||
* Reset the nodemask and zonelist iterators if memory policies can be
|
||||
@@ -5003,6 +5007,8 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
|
||||
* we always retry
|
||||
*/
|
||||
if (unlikely(nofail)) {
|
||||
unsigned int alloc_flags = ac->alloc_flags | ALLOC_MIN_RESERVE;
|
||||
|
||||
/*
|
||||
* Lacking direct_reclaim we can't do anything to reclaim memory,
|
||||
* we disregard these unreasonable nofail requests and still
|
||||
@@ -5018,7 +5024,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
|
||||
* could deplete whole memory reserves which would just make
|
||||
* the situation worse.
|
||||
*/
|
||||
page = __alloc_pages_cpuset_fallback(gfp_mask, order, ALLOC_MIN_RESERVE, ac);
|
||||
page = __alloc_pages_cpuset_fallback(gfp_mask, order, alloc_flags, ac);
|
||||
if (page)
|
||||
goto got_pg;
|
||||
|
||||
@@ -5236,7 +5242,7 @@ unsigned long alloc_pages_bulk_noprof(gfp_t gfp, int preferred_nid,
|
||||
return nr_populated;
|
||||
|
||||
failed:
|
||||
page = __alloc_pages_noprof(gfp, 0, preferred_nid, nodemask);
|
||||
page = __alloc_pages_noprof(gfp, 0, preferred_nid, nodemask, ALLOC_DEFAULT);
|
||||
if (page)
|
||||
page_array[nr_populated++] = page;
|
||||
goto out;
|
||||
@@ -5344,11 +5350,13 @@ struct page *__alloc_frozen_pages_noprof(gfp_t gfp, unsigned int order,
|
||||
{
|
||||
struct page *page;
|
||||
gfp_t alloc_gfp; /* The gfp_t that was actually used for allocation */
|
||||
struct alloc_context ac = { };
|
||||
struct alloc_context ac = {
|
||||
.alloc_flags = alloc_flags,
|
||||
};
|
||||
unsigned int fastpath_alloc_flags = alloc_flags;
|
||||
|
||||
/* Other flags could be supported later if needed. */
|
||||
if (WARN_ON(alloc_flags & ~ALLOC_NOLOCK))
|
||||
if (WARN_ON(alloc_flags & ~(ALLOC_NOLOCK | ALLOC_NO_CODETAG)))
|
||||
return NULL;
|
||||
|
||||
if (!alloc_order_allowed(gfp, order, alloc_flags))
|
||||
@@ -5421,12 +5429,12 @@ struct page *__alloc_frozen_pages_noprof(gfp_t gfp, unsigned int order,
|
||||
EXPORT_SYMBOL(__alloc_frozen_pages_noprof);
|
||||
|
||||
struct page *__alloc_pages_noprof(gfp_t gfp, unsigned int order,
|
||||
int preferred_nid, nodemask_t *nodemask)
|
||||
int preferred_nid, nodemask_t *nodemask, unsigned int alloc_flags)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
page = __alloc_frozen_pages_noprof(gfp, order, preferred_nid, nodemask,
|
||||
ALLOC_DEFAULT);
|
||||
alloc_flags);
|
||||
if (page)
|
||||
set_page_refcounted(page);
|
||||
return page;
|
||||
@@ -5440,7 +5448,7 @@ struct page *alloc_pages_node_noprof(int nid, gfp_t gfp_mask, unsigned int order
|
||||
VM_BUG_ON(nid < 0 || nid >= MAX_NUMNODES);
|
||||
warn_if_node_offline(nid, gfp_mask);
|
||||
|
||||
return __alloc_pages_noprof(gfp_mask, order, nid, NULL);
|
||||
return __alloc_pages_noprof(gfp_mask, order, nid, NULL, ALLOC_DEFAULT);
|
||||
}
|
||||
EXPORT_SYMBOL(alloc_pages_node_noprof);
|
||||
|
||||
@@ -5448,7 +5456,7 @@ struct folio *__folio_alloc_noprof(gfp_t gfp, unsigned int order, int preferred_
|
||||
nodemask_t *nodemask)
|
||||
{
|
||||
struct page *page = __alloc_pages_noprof(gfp | __GFP_COMP, order,
|
||||
preferred_nid, nodemask);
|
||||
preferred_nid, nodemask, ALLOC_DEFAULT);
|
||||
return page_rmappable_folio(page);
|
||||
}
|
||||
EXPORT_SYMBOL(__folio_alloc_noprof);
|
||||
@@ -7130,7 +7138,7 @@ static void split_free_frozen_pages(struct list_head *list, gfp_t gfp_mask)
|
||||
list_for_each_entry_safe(page, next, &list[order], lru) {
|
||||
int i;
|
||||
|
||||
post_alloc_hook(page, order, gfp_mask);
|
||||
post_alloc_hook(page, order, gfp_mask, ALLOC_DEFAULT);
|
||||
if (!order)
|
||||
continue;
|
||||
|
||||
@@ -7335,7 +7343,7 @@ int alloc_contig_frozen_range_noprof(unsigned long start, unsigned long end,
|
||||
struct page *head = pfn_to_page(start);
|
||||
|
||||
check_new_pages(head, order);
|
||||
prep_new_page(head, order, gfp_mask, 0);
|
||||
prep_new_page(head, order, gfp_mask, ALLOC_DEFAULT);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
WARN(true, "PFN range: requested [%lu, %lu), allocated [%lu, %lu)\n",
|
||||
|
||||
@@ -49,6 +49,13 @@
|
||||
#define ALLOC_HIGHATOMIC 0x200 /* Allows access to MIGRATE_HIGHATOMIC */
|
||||
#define ALLOC_NOLOCK 0x400 /* Only use spin_trylock in allocation path */
|
||||
#define ALLOC_KSWAPD 0x800 /* allow waking of kswapd, __GFP_KSWAPD_RECLAIM set */
|
||||
/*
|
||||
* Avoid alloc_tag recursion for internal allocations.
|
||||
*
|
||||
* Callers must clear_page_tag_ref() before freeing to avoid warnings from
|
||||
* alloc_tag_sub_check().
|
||||
*/
|
||||
#define ALLOC_NO_CODETAG 0x1000
|
||||
|
||||
/* Flags that allow allocations below the min watermark. */
|
||||
#define ALLOC_RESERVES (ALLOC_NON_BLOCK|ALLOC_MIN_RESERVE|ALLOC_HIGHATOMIC|ALLOC_OOM)
|
||||
@@ -84,6 +91,8 @@ struct alloc_context {
|
||||
*/
|
||||
enum zone_type highest_zoneidx;
|
||||
bool spread_dirty_pages;
|
||||
/* Only flags that are global to the whole allocation go here. */
|
||||
unsigned int alloc_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -214,7 +223,8 @@ static inline struct page *pageblock_pfn_to_page(unsigned long start_pfn,
|
||||
extern void __free_pages_core(struct page *page, unsigned int order,
|
||||
enum meminit_context context);
|
||||
|
||||
void post_alloc_hook(struct page *page, unsigned int order, gfp_t gfp_flags);
|
||||
void post_alloc_hook(struct page *page, unsigned int order, gfp_t gfp_flags,
|
||||
unsigned int alloc_flags);
|
||||
extern bool free_pages_prepare(struct page *page, unsigned int order);
|
||||
|
||||
extern int user_min_free_kbytes;
|
||||
@@ -245,7 +255,7 @@ struct page *alloc_frozen_pages_nolock_noprof(gfp_t gfp_flags, int nid, unsigned
|
||||
void free_frozen_pages_nolock(struct page *page, unsigned int order);
|
||||
|
||||
struct page *__alloc_pages_noprof(gfp_t gfp, unsigned int order, int preferred_nid,
|
||||
nodemask_t *nodemask);
|
||||
nodemask_t *nodemask, unsigned int alloc_flags);
|
||||
#define __alloc_pages(...) alloc_hooks(__alloc_pages_noprof(__VA_ARGS__))
|
||||
|
||||
extern void zone_pcp_reset(struct zone *zone);
|
||||
|
||||
@@ -57,10 +57,10 @@ static struct page *__page_frag_cache_refill(struct page_frag_cache *nc,
|
||||
gfp_mask = (gfp_mask & ~__GFP_DIRECT_RECLAIM) | __GFP_COMP |
|
||||
__GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC;
|
||||
page = __alloc_pages(gfp_mask, PAGE_FRAG_CACHE_MAX_ORDER,
|
||||
numa_mem_id(), NULL);
|
||||
numa_mem_id(), NULL, ALLOC_DEFAULT);
|
||||
#endif
|
||||
if (unlikely(!page)) {
|
||||
page = __alloc_pages(gfp, 0, numa_mem_id(), NULL);
|
||||
page = __alloc_pages(gfp, 0, numa_mem_id(), NULL, ALLOC_DEFAULT);
|
||||
order = 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user