[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <28A56ACE-55E9-48A9-9EB6-696695ABB254@nvidia.com>
Date: Wed, 21 Jan 2026 13:16:23 -0500
From: Zi Yan <ziy@...dia.com>
To: Kiryl Shutsemau <kas@...nel.org>
Cc: Andrew Morton <akpm@...ux-foundation.org>,
Muchun Song <muchun.song@...ux.dev>, David Hildenbrand <david@...nel.org>,
Matthew Wilcox <willy@...radead.org>, Usama Arif <usamaarif642@...il.com>,
Frank van der Linden <fvdl@...gle.com>, Oscar Salvador <osalvador@...e.de>,
Mike Rapoport <rppt@...nel.org>, Vlastimil Babka <vbabka@...e.cz>,
Lorenzo Stoakes <lorenzo.stoakes@...cle.com>, Baoquan He <bhe@...hat.com>,
Michal Hocko <mhocko@...e.com>, Johannes Weiner <hannes@...xchg.org>,
Jonathan Corbet <corbet@....net>, kernel-team@...a.com, linux-mm@...ck.org,
linux-kernel@...r.kernel.org, linux-doc@...r.kernel.org
Subject: Re: [PATCHv4 10/14] mm: Drop fake head checks
On 21 Jan 2026, at 11:22, Kiryl Shutsemau wrote:
> With fake head pages eliminated in the previous commit, remove the
> supporting infrastructure:
>
> - page_fixed_fake_head(): no longer needed to detect fake heads;
> - page_is_fake_head(): no longer needed;
> - page_count_writable(): no longer needed for RCU protection;
> - RCU read_lock in page_ref_add_unless(): no longer needed;
>
> This substantially simplifies compound_head() and page_ref_add_unless(),
> removing both branches and RCU overhead from these hot paths.
>
> Signed-off-by: Kiryl Shutsemau <kas@...nel.org>
> Reviewed-by: Muchun Song <muchun.song@...ux.dev>
> ---
> include/linux/page-flags.h | 93 ++------------------------------------
> include/linux/page_ref.h | 8 +---
> 2 files changed, 4 insertions(+), 97 deletions(-)
>
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index e16a4bc82856..660f9154a211 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -221,102 +221,15 @@ static __always_inline bool compound_info_has_mask(void)
> return is_power_of_2(sizeof(struct page));
> }
>
> -#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
> DECLARE_STATIC_KEY_FALSE(hugetlb_optimize_vmemmap_key);
>
> -/*
> - * Return the real head page struct iff the @page is a fake head page, otherwise
> - * return the @page itself. See Documentation/mm/vmemmap_dedup.rst.
> - */
> -static __always_inline const struct page *page_fixed_fake_head(const struct page *page)
> -{
> - if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key))
> - return page;
> -
> - /* Fake heads only exists if compound_info_has_mask() is true */
> - if (!compound_info_has_mask())
> - return page;
> -
> - /*
> - * Only addresses aligned with PAGE_SIZE of struct page may be fake head
> - * struct page. The alignment check aims to avoid access the fields (
> - * e.g. compound_info) of the @page[1]. It can avoid touch a (possibly)
> - * cold cacheline in some cases.
> - */
> - if (IS_ALIGNED((unsigned long)page, PAGE_SIZE) &&
> - test_bit(PG_head, &page->flags.f)) {
> - /*
> - * We can safely access the field of the @page[1] with PG_head
> - * because the @page is a compound page composed with at least
> - * two contiguous pages.
> - */
> - unsigned long info = READ_ONCE(page[1].compound_info);
> -
> - /* See set_compound_head() */
> - if (likely(info & 1)) {
> - unsigned long p = (unsigned long)page;
> -
> - return (const struct page *)(p & info);
> - }
> - }
> - return page;
> -}
> -
<snip>
> static __always_inline unsigned long _compound_head(const struct page *page)
> {
> unsigned long info = READ_ONCE(page->compound_info);
>
> /* Bit 0 encodes PageTail() */
> if (!(info & 1))
> - return (unsigned long)page_fixed_fake_head(page);
> + return (unsigned long)page;
Is this right? Assuming 64B struct page and 4KB page size, thus 64 struct pages
in a page, the 64th struct page (0-indexed) is mapped to the head page and
has !(info & 1). But _compound_head() should return page & info here.
Am I missing something? Thanks.
Best Regards,
Yan, Zi
Powered by blists - more mailing lists