thp_underused() decides whether a large folio on the deferred split list is underused and should be split so that its zero subpages can be reclaimed. However, the logic in it only accounts for PMD-sized folios. As preparatory work for splitting underused mTHP folios, make the logic in thp_underused() compatible with mTHP-sized folios. This uses the existing khugepaged_max_ptes_none sysctl value and scales it proportionally to the size of the folio as the threshold for how many zero-filled pages a folio may contain before it's considered underused. This introduces no functional changes for PMD-size folios. Suggested-by: Usama Arif Signed-off-by: Joanne Koong --- mm/huge_memory.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index c0892cc533a9..ea5c350b4818 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4413,24 +4413,28 @@ 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; + int nr_pages = folio_nr_pages(folio); + unsigned int max_ptes_none; int i; - if (khugepaged_max_ptes_none == HPAGE_PMD_NR - 1) + max_ptes_none = khugepaged_max_ptes_none * nr_pages / HPAGE_PMD_NR; + + if (max_ptes_none >= nr_pages - 1) return false; if (folio_contain_hwpoisoned_page(folio)) return false; - for (i = 0; i < folio_nr_pages(folio); i++) { + for (i = 0; i < nr_pages; 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 >= nr_pages - max_ptes_none) return false; } } -- 2.52.0