FAILED: patch "[PATCH] mm/huge_memory: separate out" failed to apply to 7.1-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 7.1-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-7.1.y
git checkout FETCH_HEAD
git cherry-pick -x 98bd3af0bb6bfdb0fb39cbfa05456acb374b691e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026081733-ending-blush-18e6@gregkh' --subject-prefix 'PATCH 7.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 98bd3af0bb6bfdb0fb39cbfa05456acb374b691e Mon Sep 17 00:00:00 2001
From: "Lorenzo Stoakes (ARM)" <[email protected]>
Date: Thu, 30 Jul 2026 11:55:48 +0100
Subject: [PATCH] mm/huge_memory: separate out
CONFIG_PERSISTENT_HUGE_ZERO_FOLIO logic
Rather than mixing the refcounted and non-refcounted CONFIG_PERSISTENT_HUGE_ZERO_FOLIO logic, separate the two out cleanly so it is clear what happens when this configuration option is set and what happens when it is not.
Introduce HUGE_ZERO_UNSET_PFN to abstract the ~0UL assignment, only introduce the refcount, lock and shrinker if !CONFIG_PERSISTENT_HUGE_ZERO_FOLIO, abstract initialisation and teardown, abstract the huge zero folio allocation from refcounting.
Also change a BUG_ON() to WARN_ON_ONCE() while we're at it.
No functional change intended.
mm/huge_memory.c +94 -66
@@ -78,10 +78,15 @@ static unsigned long deferred_split_scan(struct shrinker *shrink, struct shrink_control *sc);static bool split_underused_thp = true; +#define HUGE_ZERO_UNSET_PFN (~0UL) +struct folio *huge_zero_folio__read_mostly ; +unsigned long huge_zero_pfn__read_mostly =HUGE_ZERO_UNSET_PFN ; +#ifndef CONFIG_PERSISTENT_HUGE_ZERO_FOLIO static atomic_t huge_zero_refcount;static DEFINE_SPINLOCK (huge_zero_lock); -struct folio *huge_zero_folio__read_mostly ; -unsigned long huge_zero_pfn__read_mostly = ~0UL ; +static struct shrinker *huge_zero_folio_shrinker; +#endif +unsigned long huge_anon_orders_always__read_mostly ;unsigned long huge_anon_orders_madvise__read_mostly ;unsigned long huge_anon_orders_inherit__read_mostly ;
@@ -223,6 +228,47 @@ unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma,return orders; } +static struct folio *alloc_huge_zero_folio (void ) +{ +struct folio *zero_folio; + + zero_folio =folio_alloc ((GFP_TRANSHUGE | __GFP_ZERO | __GFP_ZEROTAGS) & + ~__GFP_MOVABLE, +HPAGE_PMD_ORDER ); +if (!zero_folio) { +count_vm_event (THP_ZERO_PAGE_ALLOC_FAILED ); +return NULL ; + } +folio_clear_large_rmappable (zero_folio);/* Explicitly not rmappable. */ +return zero_folio; +} + +#ifdef CONFIG_PERSISTENT_HUGE_ZERO_FOLIO +static int __init huge_zero_init (void ) +{ + huge_zero_folio =alloc_huge_zero_folio (); +if (!huge_zero_folio) { +pr_warn ("Allocating persistent huge zero folio failed\n" ); + }else { + huge_zero_pfn =folio_pfn (huge_zero_folio); +count_vm_event (THP_ZERO_PAGE_ALLOC ); + } +return 0 ; +} + +static void __init huge_zero_shrinker_exit (void ) +{ +} + +struct folio *mm_get_huge_zero_folio (struct mm_struct *mm) +{ +return huge_zero_folio; +} + +void mm_put_huge_zero_folio (struct mm_struct *mm) +{ +} +#else static bool get_huge_zero_folio (void ) {struct folio *zero_folio;
@@ -231,15 +277,9 @@ static bool get_huge_zero_folio(void)if (likely (atomic_inc_not_zero (&huge_zero_refcount)))return true; - zero_folio =folio_alloc ((GFP_TRANSHUGE | __GFP_ZERO | __GFP_ZEROTAGS) & - ~__GFP_MOVABLE, -HPAGE_PMD_ORDER ); -if (!zero_folio) { -count_vm_event (THP_ZERO_PAGE_ALLOC_FAILED ); + zero_folio =alloc_huge_zero_folio (); +if (unlikely (!zero_folio))return false; - } -/* Ensure zero folio won't have large_rmappable flag set. */ -folio_clear_large_rmappable (zero_folio);/* Paired with critical section in shrink_huge_zero_folio_scan(). */ spin_lock (&huge_zero_lock);
@@ -266,33 +306,7 @@ static void put_huge_zero_folio(void)* Counter should never go to zero here. Only shrinker can put * last reference. */ -BUG_ON (atomic_dec_and_test (&huge_zero_refcount)); -} - -struct folio *mm_get_huge_zero_folio (struct mm_struct *mm) -{ -if (IS_ENABLED (CONFIG_PERSISTENT_HUGE_ZERO_FOLIO )) -return huge_zero_folio; - -if (mm_flags_test (MMF_HUGE_ZERO_FOLIO , mm)) -return READ_ONCE (huge_zero_folio); - -if (!get_huge_zero_folio ()) -return NULL ; - -if (mm_flags_test_and_set (MMF_HUGE_ZERO_FOLIO , mm)) -put_huge_zero_folio (); - -return READ_ONCE (huge_zero_folio); -} - -void mm_put_huge_zero_folio (struct mm_struct *mm) -{ -if (IS_ENABLED (CONFIG_PERSISTENT_HUGE_ZERO_FOLIO )) -return ; - -if (mm_flags_test (MMF_HUGE_ZERO_FOLIO , mm)) -put_huge_zero_folio (); +WARN_ON_ONCE (atomic_dec_and_test (&huge_zero_refcount)); } static unsigned long shrink_huge_zero_folio_count(struct shrinker *shrink,
@@ -316,14 +330,53 @@ static unsigned long shrink_huge_zero_folio_scan(struct shrinker *shrink, zero_folio = huge_zero_folio;VM_WARN_ON_ONCE (!zero_folio);WRITE_ONCE (huge_zero_folio,NULL ); -WRITE_ONCE (huge_zero_pfn, ~0UL ); + WRITE_ONCE(huge_zero_pfn, HUGE_ZERO_UNSET_PFN); }folio_put (zero_folio);return HPAGE_PMD_NR ; } -static struct shrinker *huge_zero_folio_shrinker; +static int __init huge_zero_init (void ) +{ + huge_zero_folio_shrinker =shrinker_alloc (0 ,"thp-zero" ); +if (!huge_zero_folio_shrinker) { +shrinker_free (deferred_split_shrinker); +list_lru_destroy (&deferred_split_lru); +return -ENOMEM ; + } + + huge_zero_folio_shrinker->count_objects = shrink_huge_zero_folio_count; + huge_zero_folio_shrinker->scan_objects = shrink_huge_zero_folio_scan; +shrinker_register (huge_zero_folio_shrinker); +return 0 ; +} + +static void __init huge_zero_shrinker_exit (void ) +{ +shrinker_free (huge_zero_folio_shrinker); +} + +struct folio *mm_get_huge_zero_folio (struct mm_struct *mm) +{ +if (mm_flags_test (MMF_HUGE_ZERO_FOLIO , mm)) +return READ_ONCE (huge_zero_folio); + +if (!get_huge_zero_folio ()) +return NULL ; + +if (mm_flags_test_and_set (MMF_HUGE_ZERO_FOLIO , mm)) +put_huge_zero_folio (); + +return READ_ONCE (huge_zero_folio); +} + +void mm_put_huge_zero_folio (struct mm_struct *mm) +{ +if (mm_flags_test (MMF_HUGE_ZERO_FOLIO , mm)) +put_huge_zero_folio (); +} +#endif /* CONFIG_PERSISTENT_HUGE_ZERO_FOLIO */ #ifdef CONFIG_SYSFS static ssize_t enabled_show(struct kobject *kobj,
@@ -987,39 +1040,14 @@ static int __init thp_shrinker_init(void) deferred_split_shrinker->scan_objects = deferred_split_scan;shrinker_register (deferred_split_shrinker); -if (IS_ENABLED (CONFIG_PERSISTENT_HUGE_ZERO_FOLIO )) { -/* -* Bump the reference of the huge_zero_folio and do not -* initialize the shrinker. -* -* huge_zero_folio will always be NULL on failure. We assume -* that get_huge_zero_folio() will most likely not fail as -* thp_shrinker_init() is invoked early on during boot. -*/ -if (!get_huge_zero_folio ()) -pr_warn ("Allocating persistent huge zero folio failed\n" ); -return 0 ; - } - - huge_zero_folio_shrinker =shrinker_alloc (0 ,"thp-zero" ); -if (!huge_zero_folio_shrinker) { -shrinker_free (deferred_split_shrinker); -list_lru_destroy (&deferred_split_lru); -return -ENOMEM ; - } - - huge_zero_folio_shrinker->count_objects = shrink_huge_zero_folio_count; - huge_zero_folio_shrinker->scan_objects = shrink_huge_zero_folio_scan; -shrinker_register (huge_zero_folio_shrinker); - -return 0 ; +return huge_zero_init (); }static void __init thp_shrinker_exit (void ) { -shrinker_free (huge_zero_folio_shrinker);shrinker_free (deferred_split_shrinker);list_lru_destroy (&deferred_split_lru); +huge_zero_shrinker_exit (); }static int __init hugepage_init (void )