diff options
-rw-r--r-- | include/linux/mm.h | 16 | ||||
-rw-r--r-- | mm/memory.c | 65 |
2 files changed, 16 insertions, 65 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 600ef5ed4698..376e5c325dee 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -206,21 +206,19 @@ extern unsigned int kobjsize(const void *objp); | |||
206 | extern pgprot_t protection_map[16]; | 206 | extern pgprot_t protection_map[16]; |
207 | 207 | ||
208 | #define FAULT_FLAG_WRITE 0x01 /* Fault was a write access */ | 208 | #define FAULT_FLAG_WRITE 0x01 /* Fault was a write access */ |
209 | #define FAULT_FLAG_NONLINEAR 0x02 /* Fault was via a nonlinear mapping */ | 209 | #define FAULT_FLAG_MKWRITE 0x02 /* Fault was mkwrite of existing pte */ |
210 | #define FAULT_FLAG_MKWRITE 0x04 /* Fault was mkwrite of existing pte */ | 210 | #define FAULT_FLAG_ALLOW_RETRY 0x04 /* Retry fault if blocking */ |
211 | #define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */ | 211 | #define FAULT_FLAG_RETRY_NOWAIT 0x08 /* Don't drop mmap_sem and wait when retrying */ |
212 | #define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */ | 212 | #define FAULT_FLAG_KILLABLE 0x10 /* The fault task is in SIGKILL killable region */ |
213 | #define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */ | 213 | #define FAULT_FLAG_TRIED 0x20 /* Second try */ |
214 | #define FAULT_FLAG_TRIED 0x40 /* second try */ | 214 | #define FAULT_FLAG_USER 0x40 /* The fault originated in userspace */ |
215 | #define FAULT_FLAG_USER 0x80 /* The fault originated in userspace */ | ||
216 | 215 | ||
217 | /* | 216 | /* |
218 | * vm_fault is filled by the the pagefault handler and passed to the vma's | 217 | * vm_fault is filled by the the pagefault handler and passed to the vma's |
219 | * ->fault function. The vma's ->fault is responsible for returning a bitmask | 218 | * ->fault function. The vma's ->fault is responsible for returning a bitmask |
220 | * of VM_FAULT_xxx flags that give details about how the fault was handled. | 219 | * of VM_FAULT_xxx flags that give details about how the fault was handled. |
221 | * | 220 | * |
222 | * pgoff should be used in favour of virtual_address, if possible. If pgoff | 221 | * pgoff should be used in favour of virtual_address, if possible. |
223 | * is used, one may implement ->remap_pages to get nonlinear mapping support. | ||
224 | */ | 222 | */ |
225 | struct vm_fault { | 223 | struct vm_fault { |
226 | unsigned int flags; /* FAULT_FLAG_xxx flags */ | 224 | unsigned int flags; /* FAULT_FLAG_xxx flags */ |
diff --git a/mm/memory.c b/mm/memory.c index 9a3e73b69dad..43a53743cbb4 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1899,12 +1899,11 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr, | |||
1899 | EXPORT_SYMBOL_GPL(apply_to_page_range); | 1899 | EXPORT_SYMBOL_GPL(apply_to_page_range); |
1900 | 1900 | ||
1901 | /* | 1901 | /* |
1902 | * handle_pte_fault chooses page fault handler according to an entry | 1902 | * handle_pte_fault chooses page fault handler according to an entry which was |
1903 | * which was read non-atomically. Before making any commitment, on | 1903 | * read non-atomically. Before making any commitment, on those architectures |
1904 | * those architectures or configurations (e.g. i386 with PAE) which | 1904 | * or configurations (e.g. i386 with PAE) which might give a mix of unmatched |
1905 | * might give a mix of unmatched parts, do_swap_page and do_nonlinear_fault | 1905 | * parts, do_swap_page must check under lock before unmapping the pte and |
1906 | * must check under lock before unmapping the pte and proceeding | 1906 | * proceeding (but do_wp_page is only called after already making such a check; |
1907 | * (but do_wp_page is only called after already making such a check; | ||
1908 | * and do_anonymous_page can safely check later on). | 1907 | * and do_anonymous_page can safely check later on). |
1909 | */ | 1908 | */ |
1910 | static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd, | 1909 | static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd, |
@@ -2710,8 +2709,6 @@ void do_set_pte(struct vm_area_struct *vma, unsigned long address, | |||
2710 | entry = mk_pte(page, vma->vm_page_prot); | 2709 | entry = mk_pte(page, vma->vm_page_prot); |
2711 | if (write) | 2710 | if (write) |
2712 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 2711 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
2713 | else if (pte_file(*pte) && pte_file_soft_dirty(*pte)) | ||
2714 | entry = pte_mksoft_dirty(entry); | ||
2715 | if (anon) { | 2712 | if (anon) { |
2716 | inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); | 2713 | inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); |
2717 | page_add_new_anon_rmap(page, vma, address); | 2714 | page_add_new_anon_rmap(page, vma, address); |
@@ -2846,8 +2843,7 @@ static int do_read_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2846 | * if page by the offset is not ready to be mapped (cold cache or | 2843 | * if page by the offset is not ready to be mapped (cold cache or |
2847 | * something). | 2844 | * something). |
2848 | */ | 2845 | */ |
2849 | if (vma->vm_ops->map_pages && !(flags & FAULT_FLAG_NONLINEAR) && | 2846 | if (vma->vm_ops->map_pages && fault_around_bytes >> PAGE_SHIFT > 1) { |
2850 | fault_around_bytes >> PAGE_SHIFT > 1) { | ||
2851 | pte = pte_offset_map_lock(mm, pmd, address, &ptl); | 2847 | pte = pte_offset_map_lock(mm, pmd, address, &ptl); |
2852 | do_fault_around(vma, address, pte, pgoff, flags); | 2848 | do_fault_around(vma, address, pte, pgoff, flags); |
2853 | if (!pte_same(*pte, orig_pte)) | 2849 | if (!pte_same(*pte, orig_pte)) |
@@ -2992,7 +2988,7 @@ static int do_shared_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2992 | * The mmap_sem may have been released depending on flags and our | 2988 | * The mmap_sem may have been released depending on flags and our |
2993 | * return value. See filemap_fault() and __lock_page_or_retry(). | 2989 | * return value. See filemap_fault() and __lock_page_or_retry(). |
2994 | */ | 2990 | */ |
2995 | static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 2991 | static int do_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
2996 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2992 | unsigned long address, pte_t *page_table, pmd_t *pmd, |
2997 | unsigned int flags, pte_t orig_pte) | 2993 | unsigned int flags, pte_t orig_pte) |
2998 | { | 2994 | { |
@@ -3009,46 +3005,6 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3009 | return do_shared_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); | 3005 | return do_shared_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); |
3010 | } | 3006 | } |
3011 | 3007 | ||
3012 | /* | ||
3013 | * Fault of a previously existing named mapping. Repopulate the pte | ||
3014 | * from the encoded file_pte if possible. This enables swappable | ||
3015 | * nonlinear vmas. | ||
3016 | * | ||
3017 | * We enter with non-exclusive mmap_sem (to exclude vma changes, | ||
3018 | * but allow concurrent faults), and pte mapped but not yet locked. | ||
3019 | * We return with pte unmapped and unlocked. | ||
3020 | * The mmap_sem may have been released depending on flags and our | ||
3021 | * return value. See filemap_fault() and __lock_page_or_retry(). | ||
3022 | */ | ||
3023 | static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | ||
3024 | unsigned long address, pte_t *page_table, pmd_t *pmd, | ||
3025 | unsigned int flags, pte_t orig_pte) | ||
3026 | { | ||
3027 | pgoff_t pgoff; | ||
3028 | |||
3029 | flags |= FAULT_FLAG_NONLINEAR; | ||
3030 | |||
3031 | if (!pte_unmap_same(mm, pmd, page_table, orig_pte)) | ||
3032 | return 0; | ||
3033 | |||
3034 | if (unlikely(!(vma->vm_flags & VM_NONLINEAR))) { | ||
3035 | /* | ||
3036 | * Page table corrupted: show pte and kill process. | ||
3037 | */ | ||
3038 | print_bad_pte(vma, address, orig_pte, NULL); | ||
3039 | return VM_FAULT_SIGBUS; | ||
3040 | } | ||
3041 | |||
3042 | pgoff = pte_to_pgoff(orig_pte); | ||
3043 | if (!(flags & FAULT_FLAG_WRITE)) | ||
3044 | return do_read_fault(mm, vma, address, pmd, pgoff, flags, | ||
3045 | orig_pte); | ||
3046 | if (!(vma->vm_flags & VM_SHARED)) | ||
3047 | return do_cow_fault(mm, vma, address, pmd, pgoff, flags, | ||
3048 | orig_pte); | ||
3049 | return do_shared_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); | ||
3050 | } | ||
3051 | |||
3052 | static int numa_migrate_prep(struct page *page, struct vm_area_struct *vma, | 3008 | static int numa_migrate_prep(struct page *page, struct vm_area_struct *vma, |
3053 | unsigned long addr, int page_nid, | 3009 | unsigned long addr, int page_nid, |
3054 | int *flags) | 3010 | int *flags) |
@@ -3176,15 +3132,12 @@ static int handle_pte_fault(struct mm_struct *mm, | |||
3176 | if (pte_none(entry)) { | 3132 | if (pte_none(entry)) { |
3177 | if (vma->vm_ops) { | 3133 | if (vma->vm_ops) { |
3178 | if (likely(vma->vm_ops->fault)) | 3134 | if (likely(vma->vm_ops->fault)) |
3179 | return do_linear_fault(mm, vma, address, | 3135 | return do_fault(mm, vma, address, pte, |
3180 | pte, pmd, flags, entry); | 3136 | pmd, flags, entry); |
3181 | } | 3137 | } |
3182 | return do_anonymous_page(mm, vma, address, | 3138 | return do_anonymous_page(mm, vma, address, |
3183 | pte, pmd, flags); | 3139 | pte, pmd, flags); |
3184 | } | 3140 | } |
3185 | if (pte_file(entry)) | ||
3186 | return do_nonlinear_fault(mm, vma, address, | ||
3187 | pte, pmd, flags, entry); | ||
3188 | return do_swap_page(mm, vma, address, | 3141 | return do_swap_page(mm, vma, address, |
3189 | pte, pmd, flags, entry); | 3142 | pte, pmd, flags, entry); |
3190 | } | 3143 | } |