aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mm.h16
-rw-r--r--mm/memory.c65
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);
206extern pgprot_t protection_map[16]; 206extern 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 */
225struct vm_fault { 223struct 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,
1899EXPORT_SYMBOL_GPL(apply_to_page_range); 1899EXPORT_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 */
1910static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd, 1909static 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 */
2995static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, 2991static 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 */
3023static 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
3052static int numa_migrate_prep(struct page *page, struct vm_area_struct *vma, 3008static 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 }