diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index e35a0398db63..865ad026cab3 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -856,6 +856,39 @@ static void __show_smap(struct seq_file *m, const struct mem_size_stats *mss, seq_puts(m, " kB\n"); } +static void anon_vma_dump_recursive(struct seq_file *m, + struct vm_area_struct *vma, + struct anon_vma *parent, + int level) +{ + struct anon_vma_chain *avc; + int idx = -1; + int i; + + list_for_each_entry_reverse(avc, &vma->anon_vma_chain, same_vma) { + struct anon_vma *av = avc->anon_vma; + struct anon_vma_chain *avc2; + unsigned long anon_vma_count = 0; + + idx++; + if ((parent == NULL) ? (av != vma->anon_vma->root) : + (av->parent != parent || av == parent)) + continue; + + anon_vma_interval_tree_foreach(avc2, &av->rb_root, 0, -(pgoff_t)1) { + anon_vma_count++; + } + + seq_puts(m, (av == vma->anon_vma) ? " # " : " "); + for (i=0; iroot, atomic_read(&av->refcount), + anon_vma_count, av->num_children, av->num_active_vmas, av->parent); + anon_vma_dump_recursive(m, vma, av, level+1); + } +} + static int show_smap(struct seq_file *m, void *v) { struct vm_area_struct *vma = v; @@ -881,6 +914,14 @@ static int show_smap(struct seq_file *m, void *v) seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma)); show_smap_vma_flags(m, vma); + /* dump anon_vma information */ + if (READ_ONCE(vma->anon_vma)) { + seq_printf(m, "AnonVMAs:\n"); + anon_vma_lock_write(vma->anon_vma); + anon_vma_dump_recursive(m, vma, NULL, 0); + anon_vma_unlock_write(vma->anon_vma); + } + return 0; } diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 5cb401aa2b9d..f25e409eb1f1 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -1619,6 +1620,9 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff, struct vm_area_struct *vma; int target_result = SCAN_FAIL; + pr_warn("%s: retract_page_tables(), cc->is_khugepaged=%d, target_mm=%px\n", + __func__, cc->is_khugepaged, target_mm); + i_mmap_lock_write(mapping); vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { int result = SCAN_FAIL; @@ -1645,20 +1649,37 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff, * the anon_vma. */ if (vma->anon_vma) { + pr_warn("%s: skipping vma at 0x%lx in mm=%px because anon_vma\n", + __func__, vma->vm_start, vma->vm_mm); result = SCAN_PAGE_ANON; goto next; } addr = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); if (addr & ~HPAGE_PMD_MASK || vma->vm_end < addr + HPAGE_PMD_SIZE) { + pr_warn("%s: skipping vma at 0x%lx in mm=%px because align\n", + __func__, vma->vm_start, vma->vm_mm); result = SCAN_VMA_CHECK; goto next; } mm = vma->vm_mm; is_target = mm == target_mm && addr == target_addr; result = find_pmd_or_thp_or_none(mm, addr, &pmd); - if (result != SCAN_SUCCEED) + if (result != SCAN_SUCCEED) { + pr_warn("%s: skipping vma at 0x%lx in mm=%px because no PMD\n", + __func__, vma->vm_start, vma->vm_mm); goto next; + } + + if (cc->is_khugepaged && mm == target_mm && vma->vm_start == 0x2400000-0x1000) { + pr_warn("%s: sleeping before mmap lock...\n", __func__); + mdelay(3000); + pr_warn("%s: done sleeping\n", __func__); + } else { + pr_warn("%s: running on vma at 0x%lx in mm=%px\n", + __func__, vma->vm_start, vma->vm_mm); + } + /* * We need exclusive mmap_lock to retract page table. * @@ -1688,7 +1709,9 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff, result = SCAN_PTE_UFFD_WP; goto unlock_next; } + pr_warn("%s: about to call collapse_and_free_pmd()\n", __func__); collapse_and_free_pmd(mm, vma, addr, pmd); + pr_warn("%s: done with collapse_and_free_pmd()\n", __func__); if (!cc->is_khugepaged && is_target) result = set_huge_pmd(vma, addr, pmd, hpage); else diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c index 93e13fc17d3c..771a0124329b 100644 --- a/mm/page_vma_mapped.c +++ b/mm/page_vma_mapped.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "internal.h" @@ -16,6 +17,19 @@ static inline bool not_found(struct page_vma_mapped_walk *pvmw) static bool map_pte(struct page_vma_mapped_walk *pvmw) { pvmw->pte = pte_offset_map(pvmw->pmd, pvmw->address); + + if (strcmp(current->comm, "TEST1") == 0) { + pr_warn("%s: executing under TEST1 pvmw->vma->vm_mm==%px pvmw->vma->vm_start=0x%lx\n", + __func__, pvmw->vma->vm_mm, pvmw->vma->vm_start); + if (current->mm == pvmw->vma->vm_mm || pvmw->vma->vm_start != 0x2400000-0x1000) { + pr_warn("%s: ... continuing\n", __func__); + } else { + pr_warn("%s: ... begin delay...\n", __func__); + mdelay(3500); + pr_warn("%s: ... end delay\n", __func__); + } + } + if (!(pvmw->flags & PVMW_SYNC)) { if (pvmw->flags & PVMW_MIGRATION) { if (!is_swap_pte(*pvmw->pte))