From: Kiryl Shutsemau <kas@kernel.org>
To: Dev Jain <dev.jain@arm.com>
Cc: "Vlastimil Babka (SUSE)" <vbabka@kernel.org>,
Johannes Weiner <hannes@cmpxchg.org>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
Harry Yoo <harry@kernel.org>, Usama Arif <usama.arif@linux.dev>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>,
Brendan Jackman <brendan.jackman@linux.dev>,
Zi Yan <ziy@nvidia.com>, Shakeel Butt <shakeel.butt@linux.dev>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org, kernel-team@meta.com
Subject: Re: [PATCH v3] mm: page_alloc: make defrag_mode retries follow the promoted order
Date: Fri, 23 Oct 2026 11:59:01 +0100 [thread overview]
Message-ID: <ats7oFM-fsYdUS8y@thinkstation> (raw)
In-Reply-To: <d2b8edf0-39ab-4a44-bd0d-58230dee2fad@arm.com>
On Fri, Oct 23, 2026 at 12:09:07PM +0530, Dev Jain wrote:
> >> I ran a synthetic benchmark faulting in lots of 64k mTHP with swap enabled,
> >> defrag mode caused me to enter a warn_alloc (and 8 times more compact_stalls),
> >> which didn't happen without defrag.
Thanks for the benchmark. It reproduces on x86 in the same shape.
I think I found the problem.
Under pressure, the free order-4+ pages left are mostly in partly used
unmovable and reclaimable pageblocks. A movable request with
ALLOC_NOFRAGMENT cannot take them. But compaction_suit_allocation_order()
asks __zone_watermark_ok(), which counts free pages of every
migratetype, and returns COMPACT_SUCCESS without compacting anything.
The allocation then fails, and since compaction "succeeded", it is never
deferred.
With the diff below, compaction behaves the same with and without
defrag_mode. Medians of 15 runs of "compact-bench 99 64 16 20 0":
defrag_mode=0 defrag_mode=1 defrag_mode=1
+ diff
compact_stall 2135 32476 2290
compact_fail 668 32330 606
64K anon_fault_alloc 20689 6780 11804
64K anon_fault_fallback 776 14502 9687
64K allocation is still lower with defrag_mode. I will look into this
further.
Could you try the diff on your setup?
diff --git a/mm/compaction.c b/mm/compaction.c
index a049415512c6..09be677fff36 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -2365,6 +2365,10 @@ static enum compact_result __compact_finished(struct compact_control *cc)
!free_area_empty(area, MIGRATE_CMA))
return COMPACT_SUCCESS;
#endif
+ /* Under ALLOC_NOFRAGMENT it may only claim a whole block */
+ if ((cc->alloc_flags & ALLOC_NOFRAGMENT) && order < pageblock_order)
+ continue;
+
/*
* Job done if allocation would steal freepages from
* other migratetype buddy lists.
@@ -2510,6 +2514,43 @@ bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
return false;
}
+/*
+ * The watermark check counts free pages of every migratetype. Under
+ * ALLOC_NOFRAGMENT, a request below pageblock_order cannot take a page from a
+ * block of another migratetype unless it claims the whole block, so look for
+ * a free page the request can actually use.
+ */
+static bool compaction_free_page_usable(struct zone *zone, unsigned int order,
+ int migratetype, unsigned int alloc_flags)
+{
+ unsigned int o;
+ int mt;
+
+ if (!(alloc_flags & ALLOC_NOFRAGMENT) || order >= pageblock_order)
+ return true;
+
+ for (o = order; o < NR_PAGE_ORDERS; o++) {
+ struct free_area *area = &zone->free_area[o];
+
+ if (!free_area_empty(area, migratetype))
+ return true;
+#ifdef CONFIG_CMA
+ if ((alloc_flags & ALLOC_CMA) &&
+ !free_area_empty(area, MIGRATE_CMA))
+ return true;
+#endif
+ /* From pageblock_order up, a free block can be claimed */
+ if (o < pageblock_order)
+ continue;
+ for (mt = 0; mt < MIGRATE_PCPTYPES; mt++) {
+ if (!free_area_empty(area, mt))
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*
* Should we do compaction for target allocation order.
* Return COMPACT_SUCCESS if allocation for target order can be already
@@ -2520,7 +2561,7 @@ bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
static enum compact_result
compaction_suit_allocation_order(struct zone *zone, unsigned int order,
int highest_zoneidx, unsigned int alloc_flags,
- bool async, bool kcompactd)
+ int migratetype, bool async, bool kcompactd)
{
unsigned long free_pages;
unsigned long watermark;
@@ -2532,7 +2573,8 @@ compaction_suit_allocation_order(struct zone *zone, unsigned int order,
watermark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK);
if (__zone_watermark_ok(zone, order, watermark, highest_zoneidx,
- alloc_flags, free_pages))
+ alloc_flags, free_pages) &&
+ compaction_free_page_usable(zone, order, migratetype, alloc_flags))
return COMPACT_SUCCESS;
/*
@@ -2588,6 +2630,7 @@ compact_zone(struct compact_control *cc, struct capture_control *capc)
ret = compaction_suit_allocation_order(cc->zone, cc->order,
cc->highest_zoneidx,
cc->alloc_flags,
+ cc->migratetype,
cc->mode == MIGRATE_ASYNC,
!cc->direct_compaction);
if (ret != COMPACT_CONTINUE)
@@ -3073,7 +3116,7 @@ static bool kcompactd_node_suitable(pg_data_t *pgdat)
ret = compaction_suit_allocation_order(zone,
pgdat->kcompactd_max_order,
highest_zoneidx, alloc_flags,
- false, true);
+ MIGRATE_MOVABLE, false, true);
if (ret == COMPACT_CONTINUE)
return true;
}
@@ -3116,7 +3159,7 @@ static void kcompactd_do_work(pg_data_t *pgdat)
ret = compaction_suit_allocation_order(zone,
cc.order, zoneid, cc.alloc_flags,
- false, true);
+ MIGRATE_MOVABLE, false, true);
if (ret != COMPACT_CONTINUE)
continue;
--
Kiryl Shutsemau / Kirill A. Shutemov
next prev parent reply other threads:[~2026-10-23 10:59 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 12:55 [PATCH v3] mm: page_alloc: make defrag_mode retries follow the promoted order Kiryl Shutsemau (Meta)
2026-10-09 14:05 ` Usama Arif
2026-10-10 22:49 ` Andrew Morton
2026-10-12 10:17 ` Kiryl Shutsemau
2026-10-12 11:40 ` Vlastimil Babka (SUSE)
2026-10-13 2:28 ` Andrew Morton
2026-10-13 17:37 ` Kiryl Shutsemau
2026-10-13 18:15 ` Vlastimil Babka (SUSE)
2026-10-14 20:29 ` Johannes Weiner
2026-10-15 7:16 ` Vlastimil Babka (SUSE)
2026-10-15 12:55 ` Kiryl Shutsemau
2026-10-15 13:53 ` Vlastimil Babka (SUSE)
2026-10-15 14:39 ` Kiryl Shutsemau
2026-10-19 6:58 ` Dev Jain
2026-10-21 9:33 ` Kiryl Shutsemau
2026-10-23 6:39 ` Dev Jain
2026-10-23 10:59 ` Kiryl Shutsemau [this message]
2026-10-23 12:11 ` Kiryl Shutsemau
2026-10-23 14:46 ` Kiryl Shutsemau
2026-10-27 7:12 ` Dev Jain
2026-10-27 11:00 ` Kiryl Shutsemau
2026-10-28 7:02 ` Dev Jain
2026-10-15 12:50 ` Kiryl Shutsemau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ats7oFM-fsYdUS8y@thinkstation \
--to=kas@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=brendan.jackman@linux.dev \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.org \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@suse.com \
--cc=shakeel.butt@linux.dev \
--cc=stable@vger.kernel.org \
--cc=surenb@google.com \
--cc=usama.arif@linux.dev \
--cc=vbabka@kernel.org \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.