mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-31 22:34:33 +01:00
mm/rmap: extend rmap and migration support device-private entries
Add device-private THP support to reverse mapping infrastructure, enabling proper handling during migration and walk operations. The key changes are: - add_migration_pmd()/remove_migration_pmd(): Handle device-private entries during folio migration and splitting - page_vma_mapped_walk(): Recognize device-private THP entries during VMA traversal operations This change supports folio splitting and migration operations on device-private entries. [[email protected]: fix override of entry in remove_migration_pmd] Link: https://lkml.kernel.org/r/[email protected] [[email protected]: follow pattern used in remove_migration_pte()] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Balbir Singh <[email protected]> Reviewed-by: SeongJae Park <[email protected]> Acked-by: Zi Yan <[email protected]> Reviewed-by: Lorenzo Stoakes <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Joshua Hahn <[email protected]> Cc: Rakie Kim <[email protected]> Cc: Byungchul Park <[email protected]> Cc: Gregory Price <[email protected]> Cc: Ying Huang <[email protected]> Cc: Alistair Popple <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Baolin Wang <[email protected]> Cc: "Liam R. Howlett" <[email protected]> Cc: Nico Pache <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Dev Jain <[email protected]> Cc: Barry Song <[email protected]> Cc: Lyude Paul <[email protected]> Cc: Danilo Krummrich <[email protected]> Cc: David Airlie <[email protected]> Cc: Simona Vetter <[email protected]> Cc: Ralph Campbell <[email protected]> Cc: Mika Penttilä <[email protected]> Cc: Matthew Brost <[email protected]> Cc: Francois Dugast <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
This commit is contained in:
1 parent
368076f52e
commit
65edfda6f3
5 files changed
+71
-10
No files matched your search
+17
-3
@@ -75,12 +75,24 @@ void damon_ptep_mkold(pte_t *pte, struct vm_area_struct *vma, unsigned long addr
|
||||
void damon_pmdp_mkold(pmd_t *pmd, struct vm_area_struct *vma, unsigned long addr)
|
||||
{
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
struct folio *folio = damon_get_folio(pmd_pfn(pmdp_get(pmd)));
|
||||
pmd_t pmdval = pmdp_get(pmd);
|
||||
struct folio *folio;
|
||||
bool young = false;
|
||||
unsigned long pfn;
|
||||
|
||||
if (likely(pmd_present(pmdval)))
|
||||
pfn = pmd_pfn(pmdval);
|
||||
else
|
||||
pfn = swp_offset_pfn(pmd_to_swp_entry(pmdval));
|
||||
|
||||
folio = damon_get_folio(pfn);
|
||||
if (!folio)
|
||||
return;
|
||||
|
||||
if (pmdp_clear_young_notify(vma, addr, pmd))
|
||||
if (likely(pmd_present(pmdval)))
|
||||
young |= pmdp_clear_young_notify(vma, addr, pmd);
|
||||
young |= mmu_notifier_clear_young(vma->vm_mm, addr, addr + HPAGE_PMD_SIZE);
|
||||
if (young)
|
||||
folio_set_young(folio);
|
||||
|
||||
folio_set_idle(folio);
|
||||
@@ -199,7 +211,9 @@ static bool damon_folio_young_one(struct folio *folio,
|
||||
mmu_notifier_test_young(vma->vm_mm, addr);
|
||||
} else {
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
*accessed = pmd_young(pmdp_get(pvmw.pmd)) ||
|
||||
pmd_t pmd = pmdp_get(pvmw.pmd);
|
||||
|
||||
*accessed = (pmd_present(pmd) && pmd_young(pmd)) ||
|
||||
!folio_test_idle(folio) ||
|
||||
mmu_notifier_test_young(vma->vm_mm, addr);
|
||||
#else
|
||||
|
||||
+22
-1
@@ -4583,7 +4583,10 @@ int set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
|
||||
return 0;
|
||||
|
||||
flush_cache_range(vma, address, address + HPAGE_PMD_SIZE);
|
||||
pmdval = pmdp_invalidate(vma, address, pvmw->pmd);
|
||||
if (unlikely(!pmd_present(*pvmw->pmd)))
|
||||
pmdval = pmdp_huge_get_and_clear(vma->vm_mm, address, pvmw->pmd);
|
||||
else
|
||||
pmdval = pmdp_invalidate(vma, address, pvmw->pmd);
|
||||
|
||||
/* See folio_try_share_anon_rmap_pmd(): invalidate PMD first. */
|
||||
anon_exclusive = folio_test_anon(folio) && PageAnonExclusive(page);
|
||||
@@ -4633,6 +4636,7 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
|
||||
entry = pmd_to_swp_entry(*pvmw->pmd);
|
||||
folio_get(folio);
|
||||
pmde = folio_mk_pmd(folio, READ_ONCE(vma->vm_page_prot));
|
||||
|
||||
if (pmd_swp_soft_dirty(*pvmw->pmd))
|
||||
pmde = pmd_mksoft_dirty(pmde);
|
||||
if (is_writable_migration_entry(entry))
|
||||
@@ -4645,6 +4649,23 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
|
||||
if (folio_test_dirty(folio) && is_migration_entry_dirty(entry))
|
||||
pmde = pmd_mkdirty(pmde);
|
||||
|
||||
if (folio_is_device_private(folio)) {
|
||||
swp_entry_t entry;
|
||||
|
||||
if (pmd_write(pmde))
|
||||
entry = make_writable_device_private_entry(
|
||||
page_to_pfn(new));
|
||||
else
|
||||
entry = make_readable_device_private_entry(
|
||||
page_to_pfn(new));
|
||||
pmde = swp_entry_to_pmd(entry);
|
||||
|
||||
if (pmd_swp_soft_dirty(*pvmw->pmd))
|
||||
pmde = pmd_swp_mksoft_dirty(pmde);
|
||||
if (pmd_swp_uffd_wp(*pvmw->pmd))
|
||||
pmde = pmd_swp_mkuffd_wp(pmde);
|
||||
}
|
||||
|
||||
if (folio_test_anon(folio)) {
|
||||
rmap_t rmap_flags = RMAP_NONE;
|
||||
|
||||
|
||||
+5
-2
@@ -71,8 +71,11 @@ static bool page_idle_clear_pte_refs_one(struct folio *folio,
|
||||
referenced |= ptep_test_and_clear_young(vma, addr, pvmw.pte);
|
||||
referenced |= mmu_notifier_clear_young(vma->vm_mm, addr, addr + PAGE_SIZE);
|
||||
} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
|
||||
if (pmdp_clear_young_notify(vma, addr, pvmw.pmd))
|
||||
referenced = true;
|
||||
pmd_t pmdval = pmdp_get(pvmw.pmd);
|
||||
|
||||
if (likely(pmd_present(pmdval)))
|
||||
referenced |= pmdp_clear_young_notify(vma, addr, pvmw.pmd);
|
||||
referenced |= mmu_notifier_clear_young(vma->vm_mm, addr, addr + PMD_SIZE);
|
||||
} else {
|
||||
/* unexpected pmd-mapped page? */
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
@@ -277,6 +277,13 @@ restart:
|
||||
* cannot return prematurely, while zap_huge_pmd() has
|
||||
* cleared *pmd but not decremented compound_mapcount().
|
||||
*/
|
||||
swp_entry_t entry = pmd_to_swp_entry(pmde);
|
||||
|
||||
if (is_device_private_entry(entry)) {
|
||||
pvmw->ptl = pmd_lock(mm, pvmw->pmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((pvmw->flags & PVMW_SYNC) &&
|
||||
thp_vma_suitable_order(vma, pvmw->address,
|
||||
PMD_ORDER) &&
|
||||
|
||||
@@ -1022,9 +1022,16 @@ static int page_vma_mkclean_one(struct page_vma_mapped_walk *pvmw)
|
||||
} else {
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
pmd_t *pmd = pvmw->pmd;
|
||||
pmd_t entry;
|
||||
pmd_t entry = pmdp_get(pmd);
|
||||
|
||||
if (!pmd_dirty(*pmd) && !pmd_write(*pmd))
|
||||
/*
|
||||
* Please see the comment above (!pte_present).
|
||||
* A non present PMD is not writable from a CPU
|
||||
* perspective.
|
||||
*/
|
||||
if (!pmd_present(entry))
|
||||
continue;
|
||||
if (!pmd_dirty(entry) && !pmd_write(entry))
|
||||
continue;
|
||||
|
||||
flush_cache_range(vma, address,
|
||||
@@ -2319,6 +2326,9 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,
|
||||
while (page_vma_mapped_walk(&pvmw)) {
|
||||
/* PMD-mapped THP migration entry */
|
||||
if (!pvmw.pte) {
|
||||
__maybe_unused unsigned long pfn;
|
||||
__maybe_unused pmd_t pmdval;
|
||||
|
||||
if (flags & TTU_SPLIT_HUGE_PMD) {
|
||||
split_huge_pmd_locked(vma, pvmw.address,
|
||||
pvmw.pmd, true);
|
||||
@@ -2327,8 +2337,14 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
|
||||
subpage = folio_page(folio,
|
||||
pmd_pfn(*pvmw.pmd) - folio_pfn(folio));
|
||||
pmdval = pmdp_get(pvmw.pmd);
|
||||
if (likely(pmd_present(pmdval)))
|
||||
pfn = pmd_pfn(pmdval);
|
||||
else
|
||||
pfn = swp_offset_pfn(pmd_to_swp_entry(pmdval));
|
||||
|
||||
subpage = folio_page(folio, pfn - folio_pfn(folio));
|
||||
|
||||
VM_BUG_ON_FOLIO(folio_test_hugetlb(folio) ||
|
||||
!folio_test_pmd_mappable(folio), folio);
|
||||
|
||||
|
||||
Reference in new issue
Block a user