Commit 7f810385 authored by Dev Jain's avatar Dev Jain Committed by Andrew Morton
Browse files

khugepaged: reduce race probability between migration and khugepaged

Suppose a folio is under migration, and khugepaged is also trying to
collapse it.  collapse_pte_mapped_thp() will retrieve the folio from the
page cache via filemap_lock_folio(), thus taking a reference on the folio
and sleeping on the folio lock, since the lock is held by the migration
path.  Migration will then fail in __folio_migrate_mapping ->
folio_ref_freeze.  Reduce the probability of such a race happening
(leading to migration failure) by bailing out if we detect a PMD is marked
with a migration entry.

This fixes the migration-shared-anon-thp testcase failure on Apple M3.

Note that, this is not a "fix" since it only reduces the chance of
interference of khugepaged with migration, wherein both the kernel
functionalities are deemed "best-effort".

Link: https://lkml.kernel.org/r/20250704040417.63826-1-dev.jain@arm.com


Signed-off-by: default avatarDev Jain <dev.jain@arm.com>
Acked-by: default avatarDavid Hildenbrand <david@redhat.com>
Acked-by: default avatarOscar Salvador <osalvador@suse.de>
Reviewed-by: default avatarAnshuman Khandual <anshuman.khandual@arm.com>
Reviewed-by: default avatarZi Yan <ziy@nvidia.com>
Reviewed-by: default avatarBaolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mariano Pache <npache@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent ee58e384
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -941,6 +941,14 @@ static inline int check_pmd_state(pmd_t *pmd)

	if (pmd_none(pmde))
		return SCAN_PMD_NONE;

	/*
	 * The folio may be under migration when khugepaged is trying to
	 * collapse it. Migration success or failure will eventually end
	 * up with a present PMD mapping a folio again.
	 */
	if (is_pmd_migration_entry(pmde))
		return SCAN_PMD_MAPPED;
	if (!pmd_present(pmde))
		return SCAN_PMD_NULL;
	if (pmd_trans_huge(pmde))