summaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorZi Yan <zi.yan@cs.rutgers.edu>2017-09-08 19:11:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-08 21:26:45 -0400
commit84c3fc4e9c563d8fb91cfdf5948da48fe1af34d3 (patch)
treefc028524f9272c5ba1690d18937ebfc0bf0a0f9e /mm/memory.c
parent616b8371539a6c487404c3b8fb04078016dab4ba (diff)
mm: thp: check pmd migration entry in common path
When THP migration is being used, memory management code needs to handle pmd migration entries properly. This patch uses !pmd_present() or is_swap_pmd() (depending on whether pmd_none() needs separate code or not) to check pmd migration entries at the places where a pmd entry is present. Since pmd-related code uses split_huge_page(), split_huge_pmd(), pmd_trans_huge(), pmd_trans_unstable(), or pmd_none_or_trans_huge_or_clear_bad(), this patch: 1. adds pmd migration entry split code in split_huge_pmd(), 2. takes care of pmd migration entries whenever pmd_trans_huge() is present, 3. makes pmd_none_or_trans_huge_or_clear_bad() pmd migration entry aware. Since split_huge_page() uses split_huge_pmd() and pmd_trans_unstable() is equivalent to pmd_none_or_trans_huge_or_clear_bad(), we do not change them. Until this commit, a pmd entry should be: 1. pointing to a pte page, 2. is_swap_pmd(), 3. pmd_trans_huge(), 4. pmd_devmap(), or 5. pmd_none(). Signed-off-by: Zi Yan <zi.yan@cs.rutgers.edu> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Anshuman Khandual <khandual@linux.vnet.ibm.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: David Nellans <dnellans@nvidia.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mel Gorman <mgorman@techsingularity.net> Cc: Minchan Kim <minchan@kernel.org> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Michal Hocko <mhocko@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 13ee83b43878..886033b95fd2 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1065,7 +1065,8 @@ static inline int copy_pmd_range(struct mm_struct *dst_mm, struct mm_struct *src
1065 src_pmd = pmd_offset(src_pud, addr); 1065 src_pmd = pmd_offset(src_pud, addr);
1066 do { 1066 do {
1067 next = pmd_addr_end(addr, end); 1067 next = pmd_addr_end(addr, end);
1068 if (pmd_trans_huge(*src_pmd) || pmd_devmap(*src_pmd)) { 1068 if (is_swap_pmd(*src_pmd) || pmd_trans_huge(*src_pmd)
1069 || pmd_devmap(*src_pmd)) {
1069 int err; 1070 int err;
1070 VM_BUG_ON_VMA(next-addr != HPAGE_PMD_SIZE, vma); 1071 VM_BUG_ON_VMA(next-addr != HPAGE_PMD_SIZE, vma);
1071 err = copy_huge_pmd(dst_mm, src_mm, 1072 err = copy_huge_pmd(dst_mm, src_mm,
@@ -1326,7 +1327,7 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb,
1326 pmd = pmd_offset(pud, addr); 1327 pmd = pmd_offset(pud, addr);
1327 do { 1328 do {
1328 next = pmd_addr_end(addr, end); 1329 next = pmd_addr_end(addr, end);
1329 if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) { 1330 if (is_swap_pmd(*pmd) || pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) {
1330 if (next - addr != HPAGE_PMD_SIZE) { 1331 if (next - addr != HPAGE_PMD_SIZE) {
1331 VM_BUG_ON_VMA(vma_is_anonymous(vma) && 1332 VM_BUG_ON_VMA(vma_is_anonymous(vma) &&
1332 !rwsem_is_locked(&tlb->mm->mmap_sem), vma); 1333 !rwsem_is_locked(&tlb->mm->mmap_sem), vma);
@@ -3911,6 +3912,13 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
3911 pmd_t orig_pmd = *vmf.pmd; 3912 pmd_t orig_pmd = *vmf.pmd;
3912 3913
3913 barrier(); 3914 barrier();
3915 if (unlikely(is_swap_pmd(orig_pmd))) {
3916 VM_BUG_ON(thp_migration_supported() &&
3917 !is_pmd_migration_entry(orig_pmd));
3918 if (is_pmd_migration_entry(orig_pmd))
3919 pmd_migration_entry_wait(mm, vmf.pmd);
3920 return 0;
3921 }
3914 if (pmd_trans_huge(orig_pmd) || pmd_devmap(orig_pmd)) { 3922 if (pmd_trans_huge(orig_pmd) || pmd_devmap(orig_pmd)) {
3915 if (pmd_protnone(orig_pmd) && vma_is_accessible(vma)) 3923 if (pmd_protnone(orig_pmd) && vma_is_accessible(vma))
3916 return do_huge_pmd_numa_page(&vmf, orig_pmd); 3924 return do_huge_pmd_numa_page(&vmf, orig_pmd);