From: Greg Kroah-Hartman Date: Mon, 29 Apr 2024 14:08:08 +0000 (+0200) Subject: 6.6-stable patches X-Git-Tag: v4.19.313~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d7391a558e3ecf86d4501e4440c2b1f537f0426d;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: mm-turn-folio_test_hugetlb-into-a-pagetype.patch --- diff --git a/queue-6.6/mm-turn-folio_test_hugetlb-into-a-pagetype.patch b/queue-6.6/mm-turn-folio_test_hugetlb-into-a-pagetype.patch new file mode 100644 index 00000000000..825b50ffa31 --- /dev/null +++ b/queue-6.6/mm-turn-folio_test_hugetlb-into-a-pagetype.patch @@ -0,0 +1,239 @@ +From d99e3140a4d33e26066183ff727d8f02f56bec64 Mon Sep 17 00:00:00 2001 +From: "Matthew Wilcox (Oracle)" +Date: Thu, 21 Mar 2024 14:24:43 +0000 +Subject: mm: turn folio_test_hugetlb into a PageType + +From: Matthew Wilcox (Oracle) + +commit d99e3140a4d33e26066183ff727d8f02f56bec64 upstream. + +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. + +[willy@infradead.org: update vmcoreinfo] + Link: https://lkml.kernel.org/r/ZgGZUvsdhaT1Va-T@casper.infradead.org +Link: https://lkml.kernel.org/r/20240321142448.1645400-6-willy@infradead.org +Fixes: 9c5ccf2db04b ("mm: remove HUGETLB_PAGE_DTOR") +Signed-off-by: Matthew Wilcox (Oracle) +Reviewed-by: David Hildenbrand +Acked-by: Vlastimil Babka +Reported-by: Luis Chamberlain +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218227 +Cc: Miaohe Lin +Cc: Muchun Song +Cc: Oscar Salvador +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + 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(-) + +--- a/include/linux/page-flags.h ++++ b/include/linux/page-flags.h +@@ -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 + + #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 +@@ -915,18 +891,6 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpois + #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 + * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and +@@ -942,6 +906,7 @@ static inline bool is_page_hwpoison(stru + #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 __ClearPageA + */ + #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) +--- a/include/trace/events/mmflags.h ++++ b/include/trace/events/mmflags.h +@@ -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), \ +--- a/kernel/crash_core.c ++++ b/kernel/crash_core.c +@@ -675,11 +675,10 @@ static int __init crash_save_vmcoreinfo_ + 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); +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -1630,7 +1630,7 @@ static inline void __clear_hugetlb_destr + { + lockdep_assert_held(&hugetlb_lock); + +- folio_clear_hugetlb(folio); ++ __folio_clear_hugetlb(folio); + } + + /* +@@ -1717,7 +1717,7 @@ static void add_hugetlb_folio(struct hst + 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(str + { + 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); +@@ -2075,22 +2075,6 @@ static bool prep_compound_gigantic_folio + } + + /* +- * 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. + * + * Upon entry, the page is locked which means that page_mapping() is diff --git a/queue-6.6/series b/queue-6.6/series index b2aed3a202a..5dabd1613dc 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -154,3 +154,4 @@ mtd-diskonchip-work-around-ubsan-link-failure.patch phy-qcom-qmp-combo-fix-register-base-for-qserdes_dp_phy_mode.patch phy-qcom-qmp-combo-fix-vco-div-offset-on-v3.patch x86-tdx-preserve-shared-bit-on-mprotect.patch +mm-turn-folio_test_hugetlb-into-a-pagetype.patch