On 2/9/24 20:25, Zi Yan wrote: > On 9 Feb 2024, at 9:32, Vlastimil Babka wrote: > >> On 2/2/24 17:15, Zi Yan wrote: >>> From: Zi Yan <ziy@xxxxxxxxxx> >>> >>> migrate_pages() supports >0 order folio migration and during compaction, >>> even if compaction_alloc() cannot provide >0 order free pages, >>> migrate_pages() can split the source page and try to migrate the base pages >>> from the split. It can be a baseline and start point for adding support for >>> compacting >0 order folios. >>> >>> Suggested-by: Huang Ying <ying.huang@xxxxxxxxx> >>> Signed-off-by: Zi Yan <ziy@xxxxxxxxxx> >>> --- >>> mm/compaction.c | 43 +++++++++++++++++++++++++++++++++++-------- >>> 1 file changed, 35 insertions(+), 8 deletions(-) >>> >>> diff --git a/mm/compaction.c b/mm/compaction.c >>> index 4add68d40e8d..e43e898d2c77 100644 >>> --- a/mm/compaction.c >>> +++ b/mm/compaction.c >>> @@ -816,6 +816,21 @@ static bool too_many_isolated(struct compact_control *cc) >>> return too_many; >>> } >>> >>> +/* >>> + * 1. if the page order is larger than or equal to target_order (i.e., >>> + * cc->order and when it is not -1 for global compaction), skip it since >>> + * target_order already indicates no free page with larger than target_order >>> + * exists and later migrating it will most likely fail; >>> + * >>> + * 2. compacting > pageblock_order pages does not improve memory fragmentation, >>> + * skip them; >>> + */ >>> +static bool skip_isolation_on_order(int order, int target_order) >>> +{ >>> + return (target_order != -1 && order >= target_order) || >>> + order >= pageblock_order; >>> +} >>> + >>> /** >>> * isolate_migratepages_block() - isolate all migrate-able pages within >>> * a single pageblock >>> @@ -1010,7 +1025,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, >>> /* >>> * Regardless of being on LRU, compound pages such as THP and >>> * hugetlbfs are not to be compacted unless we are attempting >>> - * an allocation much larger than the huge page size (eg CMA). >>> + * an allocation larger than the compound page size. >>> * We can potentially save a lot of iterations if we skip them >>> * at once. The check is racy, but we can consider only valid >>> * values and the only danger is skipping too much. >>> @@ -1018,11 +1033,18 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, >>> if (PageCompound(page) && !cc->alloc_contig) { >>> const unsigned int order = compound_order(page); >>> >>> - if (likely(order <= MAX_PAGE_ORDER)) { >>> - low_pfn += (1UL << order) - 1; >>> - nr_scanned += (1UL << order) - 1; >>> + /* >>> + * Skip based on page order and compaction target order >>> + * and skip hugetlbfs pages. >>> + */ >>> + if (skip_isolation_on_order(order, cc->order) || >>> + PageHuge(page)) { >> >> Hm I'd try to avoid a new PageHuge() test here. >> >> Earlier we have a block that does >> if (PageHuge(page) && cc->alloc_contig) { >> ... >> >> think I'd rather rewrite it to handle the PageHuge() case completely and >> just make it skip the 1UL << order pages there for !cc->alloc_config. Even >> if it means duplicating a bit of the low_pfn and nr_scanned bumping code. >> >> Which reminds me the PageHuge() check there is probably still broken ATM: >> >> https://lore.kernel.org/all/8fa1c95c-4749-33dd-42ba-243e492ab109@xxxxxxx/ >> >> Even better reason not to add another one. >> If the huge page materialized since the first check, we should bail out when >> testing PageLRU later anyway. > > > OK, so basically something like: > > if (PageHuge(page)) { > if (cc->alloc_contig) { Yeah but I'd handle the !cc->alloc_contig first as that ends with a goto, and then the rest doesn't need to be "} else { ... }" with extra identation > // existing code for PageHuge(page) && cc->allc_contig > } else { > const unsigned int order = compound_order(page); > > if (order <= MAX_PAGE_ORDER) { > low_pfn += (1UL << order) - 1; > nr_scanned += (1UL << order) - 1; > } > goto isolate_fail; > } > }