Add pghint_t *hints parameter to post_alloc_hook() and
prep_new_page(). post_alloc_hook() reads PageZeroed, clears
it, and returns PGHINT_ZEROED via hints.

This provides a single point where PG_zeroed is consumed and
cleared, regardless of whether the page came through PCP or
buddy. The flag is set in page_del_and_expand() and survives
both paths until post_alloc_hook() consumes it.

Only get_page_from_freelist() passes hints through
prep_new_page(); all other callers (compaction, bulk alloc,
split, contig) pass NULL.

Signed-off-by: Michael S. Tsirkin <[email protected]>
Assisted-by: Claude:claude-opus-4-6
Assisted-by: cursor-agent:GPT-5.4-xhigh
---
 mm/compaction.c |  4 ++--
 mm/internal.h   |  3 ++-
 mm/page_alloc.c | 25 +++++++++++++++++--------
 3 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/mm/compaction.c b/mm/compaction.c
index 1e8f8eca318c..6fcce7756613 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -82,7 +82,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, NULL);
        set_page_refcounted(page);
        return page;
 }
@@ -1833,7 +1833,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, NULL);
        set_page_refcounted(&dst->page);
        if (order)
                prep_compound_page(&dst->page, order);
diff --git a/mm/internal.h b/mm/internal.h
index 686667b956c0..2964cdfcd31f 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -887,7 +887,8 @@ static inline void prep_compound_tail(struct page *head, 
int tail_idx)
        set_page_private(p, 0);
 }
 
-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,
+                    pghint_t *hints);
 extern bool free_pages_prepare(struct page *page, unsigned int order);
 
 extern int user_min_free_kbytes;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ece61d02ea96..a4cfd645599a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1863,13 +1863,21 @@ 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, pghint_t *hints)
 {
        bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) &&
                        !should_skip_init(gfp_flags);
        bool zero_tags = init && (gfp_flags & __GFP_ZEROTAGS);
+       bool zeroed = PageZeroed(page);
        int i;
 
+       __ClearPageZeroed(page);
+       if (hints)
+               *hints = zeroed ? PGHINT_ZEROED : 0;
+
+       if (zeroed && !zero_tags)
+               init = false;
+
        set_page_private(page, 0);
 
        arch_alloc_page(page, order);
@@ -1918,9 +1926,9 @@ inline void post_alloc_hook(struct page *page, unsigned 
int order,
 }
 
 static void prep_new_page(struct page *page, unsigned int order, gfp_t 
gfp_flags,
-                                                       unsigned int 
alloc_flags)
+                                       unsigned int alloc_flags, pghint_t 
*hints)
 {
-       post_alloc_hook(page, order, gfp_flags);
+       post_alloc_hook(page, order, gfp_flags, hints);
 
        if (order && (gfp_flags & __GFP_COMP))
                prep_compound_page(page, order);
@@ -3991,7 +3999,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int 
order, int alloc_flags,
                page = rmqueue(zonelist_zone(ac->preferred_zoneref), zone, 
order,
                                gfp_mask, alloc_flags, ac->migratetype);
                if (page) {
-                       prep_new_page(page, order, gfp_mask, alloc_flags);
+                       prep_new_page(page, order, gfp_mask, alloc_flags,
+                                     hints);
 
                        /*
                         * If this is a high-order atomic allocation then check
@@ -4227,7 +4236,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int 
order,
 
        /* Prep a captured page if available */
        if (page)
-               prep_new_page(page, order, gfp_mask, alloc_flags);
+               prep_new_page(page, order, gfp_mask, alloc_flags, NULL);
 
        /* Try get a page from the freelist if available */
        if (!page)
@@ -5223,7 +5232,7 @@ unsigned long alloc_pages_bulk_noprof(gfp_t gfp, int 
preferred_nid,
                }
                nr_account++;
 
-               prep_new_page(page, 0, gfp, 0);
+               prep_new_page(page, 0, gfp, 0, NULL);
                set_page_refcounted(page);
                page_array[nr_populated++] = page;
        }
@@ -6958,7 +6967,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, NULL);
                        if (!order)
                                continue;
 
@@ -7164,7 +7173,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, 0, NULL);
        } else {
                ret = -EINVAL;
                WARN(true, "PFN range: requested [%lu, %lu), allocated [%lu, 
%lu)\n",
-- 
MST


Reply via email to