aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>2015-02-11 18:27:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-11 20:06:05 -0500
commitfafaa4264eba49fd10695c193a82760558d093f4 (patch)
tree2ba4ceadd17b4b93b3ba52e410af9e3c93312c4c /include/linux
parent0b1fbfe50006c41014cc25660c0e735d21c34939 (diff)
pagewalk: improve vma handling
Current implementation of page table walker has a fundamental problem in vma handling, which started when we tried to handle vma(VM_HUGETLB). Because it's done in pgd loop, considering vma boundary makes code complicated and bug-prone. From the users viewpoint, some user checks some vma-related condition to determine whether the user really does page walk over the vma. In order to solve these, this patch moves vma check outside pgd loop and introduce a new callback ->test_walk(). Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/mm.h15
1 files changed, 12 insertions, 3 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f6106d3f3dab..3891a368e5e0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1171,10 +1171,16 @@ void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
1171 * @pte_entry: if set, called for each non-empty PTE (4th-level) entry 1171 * @pte_entry: if set, called for each non-empty PTE (4th-level) entry
1172 * @pte_hole: if set, called for each hole at all levels 1172 * @pte_hole: if set, called for each hole at all levels
1173 * @hugetlb_entry: if set, called for each hugetlb entry 1173 * @hugetlb_entry: if set, called for each hugetlb entry
1174 * *Caution*: The caller must hold mmap_sem() if @hugetlb_entry 1174 * @test_walk: caller specific callback function to determine whether
1175 * is used. 1175 * we walk over the current vma or not. A positive returned
1176 * value means "do page table walk over the current vma,"
1177 * and a negative one means "abort current page table walk
1178 * right now." 0 means "skip the current vma."
1179 * @mm: mm_struct representing the target process of page table walk
1180 * @vma: vma currently walked (NULL if walking outside vmas)
1181 * @private: private data for callbacks' usage
1176 * 1182 *
1177 * (see walk_page_range for more details) 1183 * (see the comment on walk_page_range() for more details)
1178 */ 1184 */
1179struct mm_walk { 1185struct mm_walk {
1180 int (*pmd_entry)(pmd_t *pmd, unsigned long addr, 1186 int (*pmd_entry)(pmd_t *pmd, unsigned long addr,
@@ -1186,7 +1192,10 @@ struct mm_walk {
1186 int (*hugetlb_entry)(pte_t *pte, unsigned long hmask, 1192 int (*hugetlb_entry)(pte_t *pte, unsigned long hmask,
1187 unsigned long addr, unsigned long next, 1193 unsigned long addr, unsigned long next,
1188 struct mm_walk *walk); 1194 struct mm_walk *walk);
1195 int (*test_walk)(unsigned long addr, unsigned long next,
1196 struct mm_walk *walk);
1189 struct mm_struct *mm; 1197 struct mm_struct *mm;
1198 struct vm_area_struct *vma;
1190 void *private; 1199 void *private;
1191}; 1200};
1192 1201