All of lore.kernel.org
 help / color / mirror / Atom feed
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


  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.