aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>2016-07-26 18:25:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 19:19:19 -0400
commit628d47ce98d50860d4fc1eef250126dd50622a89 (patch)
treef269b279754f33035b63dbdbe529566ed18ae7ff
parentaf9e4d5f2de2eabdc7145e077ba48b2a638465c6 (diff)
thp: skip file huge pmd on copy_huge_pmd()
copy_page_range() has a check for "Don't copy ptes where a page fault will fill them correctly." It works on VMA level. We still copy all page table entries from private mappings, even if they map page cache. We can simplify copy_huge_pmd() a bit by skipping file PMDs. We don't map file private pages with PMDs, so they only can map page cache. It's safe to skip them as they can be re-faulted later. Link: http://lkml.kernel.org/r/1466021202-61880-17-git-send-email-kirill.shutemov@linux.intel.com Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/huge_memory.c34
1 files changed, 16 insertions, 18 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index e6725c5c5a62..c11cfce4d9d9 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1098,14 +1098,15 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
1098 struct page *src_page; 1098 struct page *src_page;
1099 pmd_t pmd; 1099 pmd_t pmd;
1100 pgtable_t pgtable = NULL; 1100 pgtable_t pgtable = NULL;
1101 int ret; 1101 int ret = -ENOMEM;
1102 1102
1103 if (!vma_is_dax(vma)) { 1103 /* Skip if can be re-fill on fault */
1104 ret = -ENOMEM; 1104 if (!vma_is_anonymous(vma))
1105 pgtable = pte_alloc_one(dst_mm, addr); 1105 return 0;
1106 if (unlikely(!pgtable)) 1106
1107 goto out; 1107 pgtable = pte_alloc_one(dst_mm, addr);
1108 } 1108 if (unlikely(!pgtable))
1109 goto out;
1109 1110
1110 dst_ptl = pmd_lock(dst_mm, dst_pmd); 1111 dst_ptl = pmd_lock(dst_mm, dst_pmd);
1111 src_ptl = pmd_lockptr(src_mm, src_pmd); 1112 src_ptl = pmd_lockptr(src_mm, src_pmd);
@@ -1113,7 +1114,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
1113 1114
1114 ret = -EAGAIN; 1115 ret = -EAGAIN;
1115 pmd = *src_pmd; 1116 pmd = *src_pmd;
1116 if (unlikely(!pmd_trans_huge(pmd) && !pmd_devmap(pmd))) { 1117 if (unlikely(!pmd_trans_huge(pmd))) {
1117 pte_free(dst_mm, pgtable); 1118 pte_free(dst_mm, pgtable);
1118 goto out_unlock; 1119 goto out_unlock;
1119 } 1120 }
@@ -1136,16 +1137,13 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
1136 goto out_unlock; 1137 goto out_unlock;
1137 } 1138 }
1138 1139
1139 if (!vma_is_dax(vma)) { 1140 src_page = pmd_page(pmd);
1140 /* thp accounting separate from pmd_devmap accounting */ 1141 VM_BUG_ON_PAGE(!PageHead(src_page), src_page);
1141 src_page = pmd_page(pmd); 1142 get_page(src_page);
1142 VM_BUG_ON_PAGE(!PageHead(src_page), src_page); 1143 page_dup_rmap(src_page, true);
1143 get_page(src_page); 1144 add_mm_counter(dst_mm, MM_ANONPAGES, HPAGE_PMD_NR);
1144 page_dup_rmap(src_page, true); 1145 atomic_long_inc(&dst_mm->nr_ptes);
1145 add_mm_counter(dst_mm, MM_ANONPAGES, HPAGE_PMD_NR); 1146 pgtable_trans_huge_deposit(dst_mm, dst_pmd, pgtable);
1146 atomic_long_inc(&dst_mm->nr_ptes);
1147 pgtable_trans_huge_deposit(dst_mm, dst_pmd, pgtable);
1148 }
1149 1147
1150 pmdp_set_wrprotect(src_mm, addr, src_pmd); 1148 pmdp_set_wrprotect(src_mm, addr, src_pmd);
1151 pmd = pmd_mkold(pmd_wrprotect(pmd)); 1149 pmd = pmd_mkold(pmd_wrprotect(pmd));