diff options
author | Zi Yan <zi.yan@cs.rutgers.edu> | 2017-09-08 19:11:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-08 21:26:45 -0400 |
commit | 84c3fc4e9c563d8fb91cfdf5948da48fe1af34d3 (patch) | |
tree | fc028524f9272c5ba1690d18937ebfc0bf0a0f9e /mm/memory.c | |
parent | 616b8371539a6c487404c3b8fb04078016dab4ba (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.c | 12 |
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); |