Skip to content

Commit

Permalink
mm: postpone page table allocation until we have page to map
Browse files Browse the repository at this point in the history
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/alpine.LSU.2.11.1502202015090.14414@eggly.anvils

Link: http://lkml.kernel.org/r/1466021202-61880-10-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>
  • Loading branch information
kiryl authored and torvalds committed Jul 26, 2016
1 parent bae473a commit 7267ec0
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 127 deletions.
10 changes: 9 additions & 1 deletion include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,13 @@ struct fault_env {
* Protects pte page table if 'pte'
* is not NULL, otherwise pmd.
*/
pgtable_t prealloc_pte; /* Pre-allocated pte page table.
* vm_ops->map_pages() calls
* alloc_set_pte() from atomic context.
* do_fault_around() pre-allocates
* page table to avoid allocation from
* atomic context.
*/
};

/*
Expand Down Expand Up @@ -618,7 +625,8 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
return pte;
}

void do_set_pte(struct fault_env *fe, struct page *page);
int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg,
struct page *page);
#endif

/*
Expand Down
16 changes: 10 additions & 6 deletions mm/filemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2144,11 +2144,6 @@ void filemap_map_pages(struct fault_env *fe,
start_pgoff) {
if (iter.index > end_pgoff)
break;
fe->pte += iter.index - last_pgoff;
fe->address += (iter.index - last_pgoff) << PAGE_SHIFT;
last_pgoff = iter.index;
if (!pte_none(*fe->pte))
goto next;
repeat:
page = radix_tree_deref_slot(slot);
if (unlikely(!page))
Expand Down Expand Up @@ -2186,14 +2181,23 @@ void filemap_map_pages(struct fault_env *fe,

if (file->f_ra.mmap_miss > 0)
file->f_ra.mmap_miss--;
do_set_pte(fe, page);

fe->address += (iter.index - last_pgoff) << PAGE_SHIFT;
if (fe->pte)
fe->pte += iter.index - last_pgoff;
last_pgoff = iter.index;
if (alloc_set_pte(fe, NULL, page))
goto unlock;
unlock_page(page);
goto next;
unlock:
unlock_page(page);
skip:
put_page(page);
next:
/* Huge page is mapped? No need to proceed. */
if (pmd_trans_huge(*fe->pmd))
break;
if (iter.index == end_pgoff)
break;
}
Expand Down
Loading

0 comments on commit 7267ec0

Please sign in to comment.