Skip to content

Commit 7267ec0

Browse files
kiryltorvalds
authored andcommitted
mm: postpone page table allocation until we have page to map
The idea (and most of code) is borrowed again: from Hugh's patchset on huge tmpfs[1]. Instead of allocation pte page table upfront, we postpone this until we have page to map in hands. This approach opens possibility to map the page as huge if filesystem supports this. Comparing to Hugh's patch I've pushed page table allocation a bit further: into do_set_pte(). This way we can postpone allocation even in faultaround case without moving do_fault_around() after __do_fault(). do_set_pte() got renamed to alloc_set_pte() as it can allocate page table if required. [1] http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/1466021202-61880-10-git-send-email-kirill.shutemov@linux.intel.com Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent bae473a commit 7267ec0

File tree

3 files changed

+197
-127
lines changed

3 files changed

+197
-127
lines changed

include/linux/mm.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,13 @@ struct fault_env {
330330
* Protects pte page table if 'pte'
331331
* is not NULL, otherwise pmd.
332332
*/
333+
pgtable_t prealloc_pte; /* Pre-allocated pte page table.
334+
* vm_ops->map_pages() calls
335+
* alloc_set_pte() from atomic context.
336+
* do_fault_around() pre-allocates
337+
* page table to avoid allocation from
338+
* atomic context.
339+
*/
333340
};
334341

335342
/*
@@ -618,7 +625,8 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
618625
return pte;
619626
}
620627

621-
void do_set_pte(struct fault_env *fe, struct page *page);
628+
int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg,
629+
struct page *page);
622630
#endif
623631

624632
/*

mm/filemap.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2144,11 +2144,6 @@ void filemap_map_pages(struct fault_env *fe,
21442144
start_pgoff) {
21452145
if (iter.index > end_pgoff)
21462146
break;
2147-
fe->pte += iter.index - last_pgoff;
2148-
fe->address += (iter.index - last_pgoff) << PAGE_SHIFT;
2149-
last_pgoff = iter.index;
2150-
if (!pte_none(*fe->pte))
2151-
goto next;
21522147
repeat:
21532148
page = radix_tree_deref_slot(slot);
21542149
if (unlikely(!page))
@@ -2186,14 +2181,23 @@ void filemap_map_pages(struct fault_env *fe,
21862181

21872182
if (file->f_ra.mmap_miss > 0)
21882183
file->f_ra.mmap_miss--;
2189-
do_set_pte(fe, page);
2184+
2185+
fe->address += (iter.index - last_pgoff) << PAGE_SHIFT;
2186+
if (fe->pte)
2187+
fe->pte += iter.index - last_pgoff;
2188+
last_pgoff = iter.index;
2189+
if (alloc_set_pte(fe, NULL, page))
2190+
goto unlock;
21902191
unlock_page(page);
21912192
goto next;
21922193
unlock:
21932194
unlock_page(page);
21942195
skip:
21952196
put_page(page);
21962197
next:
2198+
/* Huge page is mapped? No need to proceed. */
2199+
if (pmd_trans_huge(*fe->pmd))
2200+
break;
21972201
if (iter.index == end_pgoff)
21982202
break;
21992203
}

0 commit comments

Comments
 (0)