Instead of passing down the head page and tail page index, pass the tail
and head pages directly, as well as the order of the compound page.
This is a preparation for changing how the head position is encoded in
the tail page.
Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
Reviewed-by: Muchun Song <muchun.song@linux.dev>
Reviewed-by: Zi Yan <ziy@nvidia.com>
---
include/linux/page-flags.h | 4 +++-
mm/hugetlb.c | 8 +++++---
mm/internal.h | 12 ++++++------
mm/mm_init.c | 2 +-
mm/page_alloc.c | 2 +-
5 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index f7a0e4af0c73..8a3694369e15 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -865,7 +865,9 @@ static inline bool folio_test_large(const struct folio *folio)
return folio_test_head(folio);
}
-static __always_inline void set_compound_head(struct page *page, struct page *head)
+static __always_inline void set_compound_head(struct page *page,
+ const struct page *head,
+ unsigned int order)
{
WRITE_ONCE(page->compound_head, (unsigned long)head + 1);
}
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 6e855a32de3d..54ba7cd05a86 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3168,6 +3168,7 @@ int __alloc_bootmem_huge_page(struct hstate *h, int nid)
/* Initialize [start_page:end_page_number] tail struct pages of a hugepage */
static void __init hugetlb_folio_init_tail_vmemmap(struct folio *folio,
+ struct hstate *h,
unsigned long start_page_number,
unsigned long end_page_number)
{
@@ -3176,6 +3177,7 @@ static void __init hugetlb_folio_init_tail_vmemmap(struct folio *folio,
struct page *page = folio_page(folio, start_page_number);
unsigned long head_pfn = folio_pfn(folio);
unsigned long pfn, end_pfn = head_pfn + end_page_number;
+ unsigned int order = huge_page_order(h);
/*
* As we marked all tail pages with memblock_reserved_mark_noinit(),
@@ -3183,7 +3185,7 @@ static void __init hugetlb_folio_init_tail_vmemmap(struct folio *folio,
*/
for (pfn = head_pfn + start_page_number; pfn < end_pfn; page++, pfn++) {
__init_single_page(page, pfn, zone, nid);
- prep_compound_tail((struct page *)folio, pfn - head_pfn);
+ prep_compound_tail(page, &folio->page, order);
set_page_count(page, 0);
}
}
@@ -3203,7 +3205,7 @@ static void __init hugetlb_folio_init_vmemmap(struct folio *folio,
__folio_set_head(folio);
ret = folio_ref_freeze(folio, 1);
VM_BUG_ON(!ret);
- hugetlb_folio_init_tail_vmemmap(folio, 1, nr_pages);
+ hugetlb_folio_init_tail_vmemmap(folio, h, 1, nr_pages);
prep_compound_head(&folio->page, huge_page_order(h));
}
@@ -3260,7 +3262,7 @@ static void __init prep_and_add_bootmem_folios(struct hstate *h,
* time as this is early in boot and there should
* be no contention.
*/
- hugetlb_folio_init_tail_vmemmap(folio,
+ hugetlb_folio_init_tail_vmemmap(folio, h,
HUGETLB_VMEMMAP_RESERVE_PAGES,
pages_per_huge_page(h));
}
diff --git a/mm/internal.h b/mm/internal.h
index d67e8bb75734..037ddcda25ff 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -879,13 +879,13 @@ static inline void prep_compound_head(struct page *page, unsigned int order)
INIT_LIST_HEAD(&folio->_deferred_list);
}
-static inline void prep_compound_tail(struct page *head, int tail_idx)
+static inline void prep_compound_tail(struct page *tail,
+ const struct page *head,
+ unsigned int order)
{
- struct page *p = head + tail_idx;
-
- p->mapping = TAIL_MAPPING;
- set_compound_head(p, head);
- set_page_private(p, 0);
+ tail->mapping = TAIL_MAPPING;
+ set_compound_head(tail, head, order);
+ set_page_private(tail, 0);
}
void post_alloc_hook(struct page *page, unsigned int order, gfp_t gfp_flags);
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 1a29a719af58..ba50f4c4337b 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -1099,7 +1099,7 @@ static void __ref memmap_init_compound(struct page *head,
struct page *page = pfn_to_page(pfn);
__init_zone_device_page(page, pfn, zone_idx, nid, pgmap);
- prep_compound_tail(head, pfn - head_pfn);
+ prep_compound_tail(page, head, order);
set_page_count(page, 0);
}
prep_compound_head(head, order);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e4104973e22f..00c7ea958767 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -744,7 +744,7 @@ void prep_compound_page(struct page *page, unsigned int order)
__SetPageHead(page);
for (i = 1; i < nr_pages; i++)
- prep_compound_tail(page, i);
+ prep_compound_tail(page + i, page, order);
prep_compound_head(page, order);
}
--
2.51.2
On 2/2/26 16:56, Kiryl Shutsemau wrote:
> Instead of passing down the head page and tail page index, pass the tail
> and head pages directly, as well as the order of the compound page.
>
> This is a preparation for changing how the head position is encoded in
> the tail page.
>
> Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
> Reviewed-by: Muchun Song <muchun.song@linux.dev>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> ---
> include/linux/page-flags.h | 4 +++-
> mm/hugetlb.c | 8 +++++---
> mm/internal.h | 12 ++++++------
> mm/mm_init.c | 2 +-
> mm/page_alloc.c | 2 +-
> 5 files changed, 16 insertions(+), 12 deletions(-)
>
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index f7a0e4af0c73..8a3694369e15 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -865,7 +865,9 @@ static inline bool folio_test_large(const struct folio *folio)
> return folio_test_head(folio);
> }
>
> -static __always_inline void set_compound_head(struct page *page, struct page *head)
> +static __always_inline void set_compound_head(struct page *page,
> + const struct page *head,
> + unsigned int order)
Two tab indents please on second+ parameter list whenever you touch code.
> {
> WRITE_ONCE(page->compound_head, (unsigned long)head + 1);
> }
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 6e855a32de3d..54ba7cd05a86 100644
[...]
> diff --git a/mm/internal.h b/mm/internal.h
> index d67e8bb75734..037ddcda25ff 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -879,13 +879,13 @@ static inline void prep_compound_head(struct page *page, unsigned int order)
> INIT_LIST_HEAD(&folio->_deferred_list);
> }
>
> -static inline void prep_compound_tail(struct page *head, int tail_idx)
> +static inline void prep_compound_tail(struct page *tail,
Just wondering whether we should call this "struct page *page" for
consistency with set_compound_head().
Or alternatively, call it also "tail" in set_compound_head().
> + const struct page *head,
> + unsigned int order)
Two tab indent, then this fits into two lines in total.
> {
> - struct page *p = head + tail_idx;
> -
> - p->mapping = TAIL_MAPPING;
> - set_compound_head(p, head);
> - set_page_private(p, 0);
> + tail->mapping = TAIL_MAPPING;
> + set_compound_head(tail, head, order);
> + set_page_private(tail, 0);
> }
Only nits, in general LGTM
Acked-by: David Hildenbrand (arm) <david@kernel.org>
--
Cheers,
David
On Wed, Feb 04, 2026 at 05:14:12PM +0100, David Hildenbrand (arm) wrote:
> On 2/2/26 16:56, Kiryl Shutsemau wrote:
> > Instead of passing down the head page and tail page index, pass the tail
> > and head pages directly, as well as the order of the compound page.
> >
> > This is a preparation for changing how the head position is encoded in
> > the tail page.
> >
> > Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
> > Reviewed-by: Muchun Song <muchun.song@linux.dev>
> > Reviewed-by: Zi Yan <ziy@nvidia.com>
> > ---
> > include/linux/page-flags.h | 4 +++-
> > mm/hugetlb.c | 8 +++++---
> > mm/internal.h | 12 ++++++------
> > mm/mm_init.c | 2 +-
> > mm/page_alloc.c | 2 +-
> > 5 files changed, 16 insertions(+), 12 deletions(-)
> >
> > diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> > index f7a0e4af0c73..8a3694369e15 100644
> > --- a/include/linux/page-flags.h
> > +++ b/include/linux/page-flags.h
> > @@ -865,7 +865,9 @@ static inline bool folio_test_large(const struct folio *folio)
> > return folio_test_head(folio);
> > }
> > -static __always_inline void set_compound_head(struct page *page, struct page *head)
> > +static __always_inline void set_compound_head(struct page *page,
> > + const struct page *head,
> > + unsigned int order)
>
> Two tab indents please on second+ parameter list whenever you touch code.
Do we have this coding style preference written down somewhere?
-tip tree wants the opposite. Documentation/process/maintainer-tip.rst:
When splitting function declarations or function calls, then please align
the first argument in the second line with the first argument in the first
line::
I want the editor to do The Right Thing™ without my brain involvement.
Having different coding styles in different corners of the kernel makes
it hard.
>
> > {
> > WRITE_ONCE(page->compound_head, (unsigned long)head + 1);
> > }
> > diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> > index 6e855a32de3d..54ba7cd05a86 100644
>
>
> [...]
>
> > diff --git a/mm/internal.h b/mm/internal.h
> > index d67e8bb75734..037ddcda25ff 100644
> > --- a/mm/internal.h
> > +++ b/mm/internal.h
> > @@ -879,13 +879,13 @@ static inline void prep_compound_head(struct page *page, unsigned int order)
> > INIT_LIST_HEAD(&folio->_deferred_list);
> > }
> > -static inline void prep_compound_tail(struct page *head, int tail_idx)
> > +static inline void prep_compound_tail(struct page *tail,
>
> Just wondering whether we should call this "struct page *page" for
> consistency with set_compound_head().
>
> Or alternatively, call it also "tail" in set_compound_head().
I will take the alternative path :)
>
> > + const struct page *head,
> > + unsigned int order)
>
> Two tab indent, then this fits into two lines in total.
>
> > {
> > - struct page *p = head + tail_idx;
> > -
> > - p->mapping = TAIL_MAPPING;
> > - set_compound_head(p, head);
> > - set_page_private(p, 0);
> > + tail->mapping = TAIL_MAPPING;
> > + set_compound_head(tail, head, order);
> > + set_page_private(tail, 0);
> > }
> Only nits, in general LGTM
>
> Acked-by: David Hildenbrand (arm) <david@kernel.org>
Thanks!
--
Kiryl Shutsemau / Kirill A. Shutemov
On 2/5/26 12:35, Kiryl Shutsemau wrote: > On Wed, Feb 04, 2026 at 05:14:12PM +0100, David Hildenbrand (arm) wrote: >> On 2/2/26 16:56, Kiryl Shutsemau wrote: >>> Instead of passing down the head page and tail page index, pass the tail >>> and head pages directly, as well as the order of the compound page. >>> >>> This is a preparation for changing how the head position is encoded in >>> the tail page. >>> >>> Signed-off-by: Kiryl Shutsemau <kas@kernel.org> >>> Reviewed-by: Muchun Song <muchun.song@linux.dev> >>> Reviewed-by: Zi Yan <ziy@nvidia.com> >>> --- >>> include/linux/page-flags.h | 4 +++- >>> mm/hugetlb.c | 8 +++++--- >>> mm/internal.h | 12 ++++++------ >>> mm/mm_init.c | 2 +- >>> mm/page_alloc.c | 2 +- >>> 5 files changed, 16 insertions(+), 12 deletions(-) >>> >>> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h >>> index f7a0e4af0c73..8a3694369e15 100644 >>> --- a/include/linux/page-flags.h >>> +++ b/include/linux/page-flags.h >>> @@ -865,7 +865,9 @@ static inline bool folio_test_large(const struct folio *folio) >>> return folio_test_head(folio); >>> } >>> -static __always_inline void set_compound_head(struct page *page, struct page *head) >>> +static __always_inline void set_compound_head(struct page *page, >>> + const struct page *head, >>> + unsigned int order) >> >> Two tab indents please on second+ parameter list whenever you touch code. > > Do we have this coding style preference written down somewhere? Good question. I assume not. But it's what we do in MM :) > > -tip tree wants the opposite. Documentation/process/maintainer-tip.rst: > > When splitting function declarations or function calls, then please align > the first argument in the second line with the first argument in the first > line:: > > I want the editor to do The Right Thing™ without my brain involvement. > Having different coding styles in different corners of the kernel makes > it hard. Yeah, but unavoidable. :) -- Cheers, David
© 2016 - 2026 Red Hat, Inc.