diff options
author | Andrea Arcangeli <aarcange@redhat.com> | 2015-09-04 18:46:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-04 19:54:41 -0400 |
commit | 6b251fc96cf2cdf1ce4b5db055547e2a5679bc77 (patch) | |
tree | 5c5fdd9cdcd1d67ff74b1ac533e5362567b65098 /mm/memory.c | |
parent | 16ba6f811dfe44bc14f7946a4b257b85476fc16e (diff) |
userfaultfd: call handle_userfault() for userfaultfd_missing() faults
This is where the page faults must be modified to call
handle_userfault() if userfaultfd_missing() is true (so if the
vma->vm_flags had VM_UFFD_MISSING set).
handle_userfault() then takes care of blocking the page fault and
delivering it to userland.
The fault flags must also be passed as parameter so the "read|write"
kind of fault can be passed to userland.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Cc: Sanidhya Kashyap <sanidhya.gatech@gmail.com>
Cc: zhang.zhanghailiang@huawei.com
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Cc: Andres Lagar-Cavilla <andreslc@google.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Hugh Dickins <hughd@google.com>
Cc: Peter Feiner <pfeiner@google.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Huangpeng (Peter)" <peter.huangpeng@huawei.com>
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 | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/mm/memory.c b/mm/memory.c index 388dcf9aa283..2961fb654369 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <linux/string.h> | 61 | #include <linux/string.h> |
62 | #include <linux/dma-debug.h> | 62 | #include <linux/dma-debug.h> |
63 | #include <linux/debugfs.h> | 63 | #include <linux/debugfs.h> |
64 | #include <linux/userfaultfd_k.h> | ||
64 | 65 | ||
65 | #include <asm/io.h> | 66 | #include <asm/io.h> |
66 | #include <asm/pgalloc.h> | 67 | #include <asm/pgalloc.h> |
@@ -2685,6 +2686,12 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2685 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); | 2686 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); |
2686 | if (!pte_none(*page_table)) | 2687 | if (!pte_none(*page_table)) |
2687 | goto unlock; | 2688 | goto unlock; |
2689 | /* Deliver the page fault to userland, check inside PT lock */ | ||
2690 | if (userfaultfd_missing(vma)) { | ||
2691 | pte_unmap_unlock(page_table, ptl); | ||
2692 | return handle_userfault(vma, address, flags, | ||
2693 | VM_UFFD_MISSING); | ||
2694 | } | ||
2688 | goto setpte; | 2695 | goto setpte; |
2689 | } | 2696 | } |
2690 | 2697 | ||
@@ -2713,6 +2720,15 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2713 | if (!pte_none(*page_table)) | 2720 | if (!pte_none(*page_table)) |
2714 | goto release; | 2721 | goto release; |
2715 | 2722 | ||
2723 | /* Deliver the page fault to userland, check inside PT lock */ | ||
2724 | if (userfaultfd_missing(vma)) { | ||
2725 | pte_unmap_unlock(page_table, ptl); | ||
2726 | mem_cgroup_cancel_charge(page, memcg); | ||
2727 | page_cache_release(page); | ||
2728 | return handle_userfault(vma, address, flags, | ||
2729 | VM_UFFD_MISSING); | ||
2730 | } | ||
2731 | |||
2716 | inc_mm_counter_fast(mm, MM_ANONPAGES); | 2732 | inc_mm_counter_fast(mm, MM_ANONPAGES); |
2717 | page_add_new_anon_rmap(page, vma, address); | 2733 | page_add_new_anon_rmap(page, vma, address); |
2718 | mem_cgroup_commit_charge(page, memcg, false); | 2734 | mem_cgroup_commit_charge(page, memcg, false); |