Re: [PATCH] mm/thp: support mTHP in thp_underused()

From: Baolin Wang

Date: Wed Jul 15 2026 - 03:36:41 EST


CC Joanne.

On 7/15/26 2:42 PM, Nico Pache wrote:
On Wed, Jul 15, 2026 at 12:28 AM Ye Liu <ye.liu@xxxxxxxxx> wrote:

From: Ye Liu <liuye@xxxxxxxxxx>

When khugepaged_max_ptes_none is configured to a non-default value,
scale it for non-PMD-mappable folios to match the logic in
collapse_max_ptes_none(), so mTHP can be classified as underused
instead of being silently skipped due to unscaled PMD-sized thresholds.

IIUC we don't actually add non-PMD folios to the deferred split list
and only operate on fully mapped folios, so consequently, we never try
to shrink them with the underused shrinker.

Right. Joanne sent a similar patch set[1] to split underused mTHP folios, but David said "needs more proper thought".

[1] https://lore.kernel.org/all/20260707201735.4113107-1-joannelkoong@xxxxxxxxx/

Signed-off-by: Ye Liu <liuye@xxxxxxxxxx>
---
mm/huge_memory.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 25612af72dca..c642bec967fa 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4489,24 +4489,29 @@ static unsigned long deferred_split_count(struct shrinker *shrink,
static bool thp_underused(struct folio *folio)
{
int num_zero_pages = 0, num_filled_pages = 0;
+ unsigned int max_ptes_none = khugepaged_max_ptes_none;
+ unsigned int folio_nr = folio_nr_pages(folio);
int i;

- if (khugepaged_max_ptes_none == HPAGE_PMD_NR - 1)
+ if (!folio_test_pmd_mappable(folio)) {
+ if (max_ptes_none == HPAGE_PMD_NR - 1)
+ max_ptes_none = folio_nr - 1;
+ else if (max_ptes_none)
+ return false;
+ }
+
+ if (max_ptes_none == folio_nr - 1)
return false;

if (folio_contain_hwpoisoned_page(folio))
return false;

- for (i = 0; i < folio_nr_pages(folio); i++) {
+ for (i = 0; i < folio_nr; i++) {
if (pages_identical(folio_page(folio, i), ZERO_PAGE(0))) {
- if (++num_zero_pages > khugepaged_max_ptes_none)
+ if (++num_zero_pages > max_ptes_none)
return true;
} else {
- /*
- * Another path for early exit once the number
- * of non-zero filled pages exceeds threshold.
- */
- if (++num_filled_pages >= HPAGE_PMD_NR - khugepaged_max_ptes_none)
+ if (++num_filled_pages >= folio_nr - max_ptes_none)
return false;
}
}
--
2.43.0