[PATCH 4/4] mm: Fix demotion gfp by preserving initial gfp reclaim policy

From: Alexandre Ghiti

Date: Wed Mar 11 2026 - 07:04:52 EST


When the src folio is a hugetlb page, htlb_modify_alloc_mask() will
unconditionally enable reclaim. But we have to preserve initial gfp
flags which, in the case of demotion, prevent direct reclaim.

Reported-by: Gregory Price <gourry@xxxxxxxxxx>
Closes: https://lore.kernel.org/linux-mm/aXkfBF5bdnTZ7t7e@gourry-fedora-PF4VCD3F/
Fixes: 19fc7bed252c ("mm/migrate: introduce a standard migration target allocation function")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Alexandre Ghiti <alex@xxxxxxxx>
---
mm/migrate.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/mm/migrate.c b/mm/migrate.c
index ee533a4d38db..d44a34d37007 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -2169,13 +2169,13 @@ int migrate_pages(struct list_head *from, new_folio_t get_new_folio,
struct folio *alloc_migration_target(struct folio *src, unsigned long private)
{
struct migration_target_control *mtc;
- gfp_t gfp_mask;
+ gfp_t gfp_mask, gfp_entry;
unsigned int order = 0;
int nid;
enum zone_type zidx;

mtc = (struct migration_target_control *)private;
- gfp_mask = mtc->gfp_mask;
+ gfp_mask = gfp_entry = mtc->gfp_mask;
nid = mtc->nid;
if (nid == NUMA_NO_NODE)
nid = folio_nid(src);
@@ -2184,6 +2184,8 @@ struct folio *alloc_migration_target(struct folio *src, unsigned long private)
struct hstate *h = folio_hstate(src);

gfp_mask = htlb_modify_alloc_mask(h, gfp_mask);
+ gfp_mask = (gfp_mask & ~__GFP_RECLAIM) | (gfp_entry & __GFP_RECLAIM);
+
return alloc_hugetlb_folio_nodemask(h, nid,
mtc->nmask, gfp_mask,
htlb_allow_alloc_fallback(mtc->reason));
--
2.53.0