Re: [PATCH v3] mm, compaction: Skip all non-migratable pages during scan

From: Khalid Aziz
Date: Mon May 22 2023 - 11:13:34 EST


On 5/21/23 23:55, Huang, Ying wrote:
David Hildenbrand <david@xxxxxxxxxx> writes:

On 18.05.23 03:09, Huang, Ying wrote:
David Hildenbrand <david@xxxxxxxxxx> writes:

On 17.05.23 18:15, Khalid Aziz wrote:
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 kcompactd scanning vfio pinned pages over and over again that can
not be migrated.

How will this change affect alloc_contig_range(), such as used for CMA
allocations or virtio-mem? alloc_contig_range() ends up calling
isolate_migratepages_range() -> isolate_migratepages_block().
IIUC, cc->alloc_contig can be used to distinguish contiguous
allocation
and compaction. And, from the original commit which introduced
anonymous pages skipping (commit 119d6d59dcc0 ("mm, compaction: avoid
isolating pinned pages ")) and this patch, large number of migration
failure during compaction causes real issue too. So, I suggest to use
cc->alloc_contig here.

Agreed. I further wonder if we want to special-case the !alloc_contig
case also for MIGRATE_CMA and ZONE_MOVABLE, where we cannot have
longterm page pinnings (e.g., vfio pinned pages).

This makes sense. The skipping is more accurate in this way.



Something like this?

diff --git a/mm/compaction.c b/mm/compaction.c
index f04c00981172..014e21d3d7e9 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1025,7 +1025,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
* lru_lock and isolating it unnecessarily
*/
mapping = page_mapping(page);
- if (page_has_extra_refs(page))
+ if (!cc->alloc_contig && page_has_extra_refs(page))
goto isolate_fail_put;

/*


Thanks,
Khalid