The patch titled Subject: mm, compaction: Skip all non-migratable pages during scan has been added to the -mm mm-unstable branch. Its filename is mm-compaction-skip-all-non-migratable-pages-during-scan.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-compaction-skip-all-non-migratable-pages-during-scan.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via the mm-everything branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there every 2-3 working days ------------------------------------------------------ From: Khalid Aziz <khalid.aziz@xxxxxxxxxx> Subject: mm, compaction: Skip all non-migratable pages during scan Date: Fri, 12 May 2023 13:00:00 -0600 Pages pinned in memory through extra refcounts can not be migrated. Currently as isolate_migratepages_block() scans pages for compaction, it skips any pinned anonymous pages. All non-migratable pages should be skipped and not just the anonymous pinned pages. This patch adds a check for extra refcounts on a page to determine if the page can be migrated. This was seen as a real issue on a customer workload where a large number of pages were pinned by vfio on the host and any attempts to allocate hugepages resulted in significant amount of cpu time spent in either direct compaction or in kcompatd scanning vfio pinned pages over and over again that can not be migrated. Link: https://lkml.kernel.org/r/20230512190000.103737-1-khalid.aziz@xxxxxxxxxx Signed-off-by: Khalid Aziz <khalid.aziz@xxxxxxxxxx> Suggested-by: Steve Sistare <steven.sistare@xxxxxxxxxx> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/compaction.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) --- a/mm/compaction.c~mm-compaction-skip-all-non-migratable-pages-during-scan +++ a/mm/compaction.c @@ -765,6 +765,34 @@ static bool too_many_isolated(pg_data_t return too_many; } +/* + * Check if this base page should be skipped from isolation because + * it has extra refcounts that will prevent it from being migrated. + * This function is called for regular pages only, and not + * for THP or hugetlbfs pages. This code is inspired by similar code + * in migrate_vma_check_page(), can_split_folio() and + * folio_migrate_mapping() + */ +static inline bool page_has_extrarefs(struct page *page, + struct address_space *mapping) +{ + unsigned long extra_refs; + + /* anonymous page can have extra ref from swap cache */ + if (mapping) + extra_refs = 1 + PagePrivate(page); + else + extra_refs = PageSwapCache(page) ? 1 : 0; + + /* + * This is an admittedly racy check but good enough to determine + * if a page is pinned and can not be migrated + */ + if ((page_ref_count(page) - extra_refs) > page_mapcount(page)) + return true; + return false; +} + /** * isolate_migratepages_block() - isolate all migrate-able pages within * a single pageblock @@ -1003,12 +1031,12 @@ isolate_migratepages_block(struct compac goto isolate_fail; /* - * Migration will fail if an anonymous page is pinned in memory, - * so avoid taking lru_lock and isolating it unnecessarily in an - * admittedly racy check. + * Migration will fail if a page has extra refcounts + * preventing it from migrating, so avoid taking + * lru_lock and isolating it unnecessarily */ mapping = page_mapping(page); - if (!mapping && (page_count(page) - 1) > total_mapcount(page)) + if (page_has_extrarefs(page, mapping)) goto isolate_fail_put; /* _ Patches currently in -mm which might be from khalid.aziz@xxxxxxxxxx are mm-compaction-skip-all-non-migratable-pages-during-scan.patch