FAILED: patch "[PATCH] mm: turn folio_test_hugetlb into a PageType" failed to apply to 6.6-stable tree
Subsystems (5)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x d99e3140a4d33e26066183ff727d8f02f56bec64
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024042908-squint-barometer-51de@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..
Possible dependencies:
d99e3140a4d3 ("mm: turn folio_test_hugetlb into a PageType")29cfe7556bfd ("mm: constify more page/folio tests")443cbaf9e2fd ("crash: split vmcoreinfo exporting code out from crash_core.c")85fcde402db1 ("kexec: split crashkernel reservation code out from crash_core.c")55c49fee57af ("mm/vmalloc: remove vmap_area_list")d093602919ad ("mm: vmalloc: remove global vmap_area_root rb-tree")7fa8cee00316 ("mm: vmalloc: move vmap_init_free_space() down in vmalloc.c")4a693ce65b18 ("kdump: defer the insertion of crashkernel resources")9f2a63523582 ("Merge tag 'mm-nonmm-stable-2024-01-09-10-33' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d99e3140a4d33e26066183ff727d8f02f56bec64 Mon Sep 17 00:00:00 2001
From: "Matthew Wilcox (Oracle)" <[email protected]>
Date: Thu, 21 Mar 2024 14:24:43 +0000
Subject: [PATCH] mm: turn folio_test_hugetlb into a PageType
The current folio_test_hugetlb() can be fooled by a concurrent folio split into returning true for a folio which has never belonged to hugetlbfs. This can't happen if the caller holds a refcount on it, but we have a few places (memory-failure, compaction, procfs) which do not and should not take a speculative reference.
Since hugetlb pages do not use individual page mapcounts (they are always fully mapped and use the entire_mapcount field to record the number of mappings), the PageType field is available now that page_mapcount() ignores the value in this field.
In compaction and with CONFIG_DEBUG_VM enabled, the current implementation can result in an oops, as reported by Luis. This happens since 9c5ccf2db04b ("mm: remove HUGETLB_PAGE_DTOR") effectively added some VM_BUG_ON() checks in the PageHuge() testing path.
include/linux/page-flags.h +33 -37
@@ -190,7 +190,6 @@ enum pageflags {/* At least one page in this folio has the hwpoison flag set */ PG_has_hwpoisoned = PG_error, - PG_hugetlb = PG_active, PG_large_rmappable = PG_workingset, /* anon or file-backed */ };
@@ -876,29 +875,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable)#define PG_head_mask ((1UL << PG_head)) -#ifdef CONFIG_HUGETLB_PAGE -int PageHuge (const struct page *page); -SETPAGEFLAG(HugeTLB, hugetlb, PF_SECOND) -CLEARPAGEFLAG (HugeTLB, hugetlb,PF_SECOND ) - -/** -* folio_test_hugetlb - Determine if the folio belongs to hugetlbfs -* @folio: The folio to test. -* -* Context: Any context. Caller should have a reference on the folio to -* prevent it from being turned into a tail page. -* Return: True for hugetlbfs folios, false for anon folios or folios -* belonging to other filesystems. - */ -static inline bool folio_test_hugetlb (const struct folio *folio) -{ -return folio_test_large (folio) && -test_bit (PG_hugetlb,const_folio_flags (folio,1 )); -} -#else -TESTPAGEFLAG_FALSE(Huge, hugetlb) -#endif -#ifdef CONFIG_TRANSPARENT_HUGEPAGE /* * PageHuge() only returns true for hugetlbfs pages, but not for
@@ -954,18 +930,6 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned) TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)#endif -/* -* Check if a page is currently marked HWPoisoned. Note that this check is -* best effort only and inherently racy: there is no way to synchronize with -* failing hardware. -*/ -static inline bool is_page_hwpoison (struct page *page) -{ -if (PageHWPoison (page)) -return true; -return PageHuge (page) &&PageHWPoison (compound_head (page)); -} -/* * For pages that are never mapped to userspace (and aren't PageSlab), * page_type may be used. Because it is initialised to -1, we invert the
@@ -982,6 +946,7 @@ static inline bool is_page_hwpoison(struct page *page)#define PG_offline 0x00000100#define PG_table 0x00000200#define PG_guard 0x00000400 +#define PG_hugetlb 0x00000800#define PageType (page, flag) \ ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
@@ -1076,6 +1041,37 @@ PAGE_TYPE_OPS(Table, table, pgtable)*/ PAGE_TYPE_OPS(Guard, guard, guard) +#ifdef CONFIG_HUGETLB_PAGE +FOLIO_TYPE_OPS(hugetlb, hugetlb) +#else +FOLIO_TEST_FLAG_FALSE(hugetlb) +#endif + +/** +* PageHuge - Determine if the page belongs to hugetlbfs +* @page: The page to test. +* +* Context: Any context. +* Return: True for hugetlbfs pages, false for anon pages or pages +* belonging to other filesystems. +*/ +static inline bool PageHuge (const struct page *page) +{ +return folio_test_hugetlb (page_folio (page)); +} + +/* +* Check if a page is currently marked HWPoisoned. Note that this check is +* best effort only and inherently racy: there is no way to synchronize with +* failing hardware. +*/ +static inline bool is_page_hwpoison (struct page *page) +{ +if (PageHWPoison (page)) +return true; +return PageHuge (page) &&PageHWPoison (compound_head (page)); +} +extern bool is_free_buddy_page (struct page *page);PAGEFLAG (Isolated, isolated,PF_ANY );
@@ -1142,7 +1138,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)*/ #define PAGE_FLAGS_SECOND \ (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \ - 1UL << PG_hugetlb | 1UL << PG_large_rmappable) + 1UL << PG_large_rmappable)#define PAGE_FLAGS_PRIVATE \ (1UL << PG_private | 1UL << PG_private_2)
include/trace/events/mmflags.h +1 -0
@@ -135,6 +135,7 @@ IF_HAVE_PG_ARCH_X(arch_3)#define DEF_PAGETYPE_NAME (_name) { PG_##_name, __stringify(_name) }#define __def_pagetype_names \ + DEF_PAGETYPE_NAME(hugetlb), \ DEF_PAGETYPE_NAME(offline), \ DEF_PAGETYPE_NAME(guard), \ DEF_PAGETYPE_NAME(table), \
kernel/vmcore_info.c +2 -3
@@ -205,11 +205,10 @@ static int __init crash_save_vmcoreinfo_init(void)VMCOREINFO_NUMBER (PG_head_mask);#define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)VMCOREINFO_NUMBER (PAGE_BUDDY_MAPCOUNT_VALUE ); -#ifdef CONFIG_HUGETLB_PAGE -VMCOREINFO_NUMBER (PG_hugetlb); +#define PAGE_HUGETLB_MAPCOUNT_VALUE (~PG_hugetlb) +VMCOREINFO_NUMBER (PAGE_HUGETLB_MAPCOUNT_VALUE );#define PAGE_OFFLINE_MAPCOUNT_VALUE (~PG_offline)VMCOREINFO_NUMBER (PAGE_OFFLINE_MAPCOUNT_VALUE ); -#endif #ifdef CONFIG_KALLSYMS VMCOREINFO_SYMBOL (kallsyms_names);
mm/hugetlb.c +3 -19
@@ -1624,7 +1624,7 @@ static inline void __clear_hugetlb_destructor(struct hstate *h, {lockdep_assert_held (&hugetlb_lock); -folio_clear_hugetlb (folio); +__folio_clear_hugetlb (folio); }/*
@@ -1711,7 +1711,7 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio, h->surplus_huge_pages_node[nid]++; } -folio_set_hugetlb (folio); +__folio_set_hugetlb (folio);folio_change_private (folio,NULL );/* * We have to set hugetlb_vmemmap_optimized again as above
@@ -2049,7 +2049,7 @@ static void __prep_account_new_huge_page(struct hstate *h, int nid)static void init_new_hugetlb_folio (struct hstate *h,struct folio *folio) { -folio_set_hugetlb (folio); +__folio_set_hugetlb (folio);INIT_LIST_HEAD (&folio->lru);hugetlb_set_folio_subpool (folio,NULL );set_hugetlb_cgroup (folio,NULL );
@@ -2159,22 +2159,6 @@ static bool prep_compound_gigantic_folio_for_demote(struct folio *folio,return __prep_compound_gigantic_folio (folio, order, true); } -/* -* PageHuge() only returns true for hugetlbfs pages, but not for normal or -* transparent huge pages. See the PageTransHuge() documentation for more -* details. -*/ -int PageHuge (const struct page *page) -{ -const struct folio *folio; - -if (!PageCompound (page)) -return 0 ; - folio =page_folio (page); -return folio_test_hugetlb (folio); -} -EXPORT_SYMBOL_GPL (PageHuge); -/* * Find and lock address space (mapping) in write mode. *
PATCH 1/1 mm: turn folio_test_hugetlb into a PageType
The current folio_test_hugetlb() can be fooled by a concurrent folio split into returning true for a folio which has never belonged to hugetlbfs. This can't happen if the caller holds a refcount on it, but we have a few places (memory-failure, compaction, procfs) which do not and should not take a speculative reference.
Since hugetlb pages do not use individual page mapcounts (they are always fully mapped and use the entire_mapcount field to record the number of mappings), the PageType field is available now that page_mapcount() ignores the value in this field.
In compaction and with CONFIG_DEBUG_VM enabled, the current implementation can result in an oops, as reported by Luis. This happens since 9c5ccf2db04b ("mm: remove HUGETLB_PAGE_DTOR") effectively added some VM_BUG_ON() checks in the PageHuge() testing path.
--- include/linux/page-flags.h | 70 ++++++++++++++++------------------ include/trace/events/mmflags.h | 1 + kernel/crash_core.c | 5 +-- mm/hugetlb.c | 22 ++--------- 4 files changed, 39 insertions(+), 59 deletions(-)
include/linux/page-flags.h +33 -37
@@ -190,7 +190,6 @@ enum pageflags {/* At least one page in this folio has the hwpoison flag set */ PG_has_hwpoisoned = PG_error, - PG_hugetlb = PG_active, PG_large_rmappable = PG_workingset, /* anon or file-backed */ };
@@ -836,29 +835,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable)#define PG_head_mask ((1UL << PG_head)) -#ifdef CONFIG_HUGETLB_PAGE -int PageHuge (struct page *page); -SETPAGEFLAG(HugeTLB, hugetlb, PF_SECOND) -CLEARPAGEFLAG (HugeTLB, hugetlb,PF_SECOND ) - -/** -* folio_test_hugetlb - Determine if the folio belongs to hugetlbfs -* @folio: The folio to test. -* -* Context: Any context. Caller should have a reference on the folio to -* prevent it from being turned into a tail page. -* Return: True for hugetlbfs folios, false for anon folios or folios -* belonging to other filesystems. - */ -static inline bool folio_test_hugetlb (struct folio *folio) -{ -return folio_test_large (folio) && -test_bit (PG_hugetlb,folio_flags (folio,1 )); -} -#else -TESTPAGEFLAG_FALSE(Huge, hugetlb) -#endif -#ifdef CONFIG_TRANSPARENT_HUGEPAGE /* * PageHuge() only returns true for hugetlbfs pages, but not for
@@ -914,18 +890,6 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned) TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)#endif -/* -* Check if a page is currently marked HWPoisoned. Note that this check is -* best effort only and inherently racy: there is no way to synchronize with -* failing hardware. -*/ -static inline bool is_page_hwpoison (struct page *page) -{ -if (PageHWPoison (page)) -return true; -return PageHuge (page) &&PageHWPoison (compound_head (page)); -} -/* * For pages that are never mapped to userspace (and aren't PageSlab), * page_type may be used. Because it is initialised to -1, we invert the
@@ -942,6 +906,7 @@ static inline bool is_page_hwpoison(struct page *page)#define PG_offline 0x00000100#define PG_table 0x00000200#define PG_guard 0x00000400 +#define PG_hugetlb 0x00000800#define PageType (page, flag) \ ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
@@ -1036,6 +1001,37 @@ PAGE_TYPE_OPS(Table, table, pgtable)*/ PAGE_TYPE_OPS(Guard, guard, guard) +#ifdef CONFIG_HUGETLB_PAGE +FOLIO_TYPE_OPS(hugetlb, hugetlb) +#else +FOLIO_TEST_FLAG_FALSE(hugetlb) +#endif + +/** +* PageHuge - Determine if the page belongs to hugetlbfs +* @page: The page to test. +* +* Context: Any context. +* Return: True for hugetlbfs pages, false for anon pages or pages +* belonging to other filesystems. +*/ +static inline bool PageHuge (const struct page *page) +{ +return folio_test_hugetlb (page_folio (page)); +} + +/* +* Check if a page is currently marked HWPoisoned. Note that this check is +* best effort only and inherently racy: there is no way to synchronize with +* failing hardware. +*/ +static inline bool is_page_hwpoison (struct page *page) +{ +if (PageHWPoison (page)) +return true; +return PageHuge (page) &&PageHWPoison (compound_head (page)); +} +extern bool is_free_buddy_page (struct page *page);PAGEFLAG (Isolated, isolated,PF_ANY );
@@ -1102,7 +1098,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)*/ #define PAGE_FLAGS_SECOND \ (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \ - 1UL << PG_hugetlb | 1UL << PG_large_rmappable) + 1UL << PG_large_rmappable)#define PAGE_FLAGS_PRIVATE \ (1UL << PG_private | 1UL << PG_private_2)
include/trace/events/mmflags.h +1 -0
@@ -135,6 +135,7 @@ IF_HAVE_PG_ARCH_X(arch_3)#define DEF_PAGETYPE_NAME (_name) { PG_##_name, __stringify(_name) }#define __def_pagetype_names \ + DEF_PAGETYPE_NAME(hugetlb), \ DEF_PAGETYPE_NAME(offline), \ DEF_PAGETYPE_NAME(guard), \ DEF_PAGETYPE_NAME(table), \
kernel/crash_core.c +2 -3
@@ -675,11 +675,10 @@ static int __init crash_save_vmcoreinfo_init(void)VMCOREINFO_NUMBER (PG_head_mask);#define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)VMCOREINFO_NUMBER (PAGE_BUDDY_MAPCOUNT_VALUE ); -#ifdef CONFIG_HUGETLB_PAGE -VMCOREINFO_NUMBER (PG_hugetlb); +#define PAGE_HUGETLB_MAPCOUNT_VALUE (~PG_hugetlb) +VMCOREINFO_NUMBER (PAGE_HUGETLB_MAPCOUNT_VALUE );#define PAGE_OFFLINE_MAPCOUNT_VALUE (~PG_offline)VMCOREINFO_NUMBER (PAGE_OFFLINE_MAPCOUNT_VALUE ); -#endif #ifdef CONFIG_KALLSYMS VMCOREINFO_SYMBOL (kallsyms_names);
mm/hugetlb.c +3 -19
@@ -1630,7 +1630,7 @@ static inline void __clear_hugetlb_destructor(struct hstate *h, {lockdep_assert_held (&hugetlb_lock); -folio_clear_hugetlb (folio); +__folio_clear_hugetlb (folio); }/*
@@ -1717,7 +1717,7 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio, h->surplus_huge_pages_node[nid]++; } -folio_set_hugetlb (folio); +__folio_set_hugetlb (folio);folio_change_private (folio,NULL );/* * We have to set hugetlb_vmemmap_optimized again as above
@@ -1971,7 +1971,7 @@ static void __prep_new_hugetlb_folio(struct hstate *h, struct folio *folio) {hugetlb_vmemmap_optimize (h, &folio->page);INIT_LIST_HEAD (&folio->lru); -folio_set_hugetlb (folio); +__folio_set_hugetlb (folio);hugetlb_set_folio_subpool (folio,NULL );set_hugetlb_cgroup (folio,NULL );set_hugetlb_cgroup_rsvd (folio,NULL );
@@ -2074,22 +2074,6 @@ static bool prep_compound_gigantic_folio_for_demote(struct folio *folio,return __prep_compound_gigantic_folio (folio, order, true); } -/* -* PageHuge() only returns true for hugetlbfs pages, but not for normal or -* transparent huge pages. See the PageTransHuge() documentation for more -* details. -*/ -int PageHuge (struct page *page) -{ -struct folio *folio; - -if (!PageCompound (page)) -return 0 ; - folio =page_folio (page); -return folio_test_hugetlb (folio); -} -EXPORT_SYMBOL_GPL (PageHuge); -/* * Find and lock address space (mapping) in write mode. *
Signature · 1 line
2.43.0