diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/mm/memory.c b/mm/memory.c index 5b4ad5e4f98d..cf6873e91c6a 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1945,6 +1945,15 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1945 | * get_user_pages(.write=1, .force=1). | 1945 | * get_user_pages(.write=1, .force=1). |
1946 | */ | 1946 | */ |
1947 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { | 1947 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { |
1948 | struct vm_fault vmf; | ||
1949 | int tmp; | ||
1950 | |||
1951 | vmf.virtual_address = (void __user *)(address & | ||
1952 | PAGE_MASK); | ||
1953 | vmf.pgoff = old_page->index; | ||
1954 | vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE; | ||
1955 | vmf.page = old_page; | ||
1956 | |||
1948 | /* | 1957 | /* |
1949 | * Notify the address space that the page is about to | 1958 | * Notify the address space that the page is about to |
1950 | * become writable so that it can prohibit this or wait | 1959 | * become writable so that it can prohibit this or wait |
@@ -1956,8 +1965,12 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1956 | page_cache_get(old_page); | 1965 | page_cache_get(old_page); |
1957 | pte_unmap_unlock(page_table, ptl); | 1966 | pte_unmap_unlock(page_table, ptl); |
1958 | 1967 | ||
1959 | if (vma->vm_ops->page_mkwrite(vma, old_page) < 0) | 1968 | tmp = vma->vm_ops->page_mkwrite(vma, &vmf); |
1969 | if (unlikely(tmp & | ||
1970 | (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) { | ||
1971 | ret = tmp; | ||
1960 | goto unwritable_page; | 1972 | goto unwritable_page; |
1973 | } | ||
1961 | 1974 | ||
1962 | /* | 1975 | /* |
1963 | * Since we dropped the lock we need to revalidate | 1976 | * Since we dropped the lock we need to revalidate |
@@ -2106,7 +2119,7 @@ oom: | |||
2106 | 2119 | ||
2107 | unwritable_page: | 2120 | unwritable_page: |
2108 | page_cache_release(old_page); | 2121 | page_cache_release(old_page); |
2109 | return VM_FAULT_SIGBUS; | 2122 | return ret; |
2110 | } | 2123 | } |
2111 | 2124 | ||
2112 | /* | 2125 | /* |
@@ -2648,9 +2661,14 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2648 | * to become writable | 2661 | * to become writable |
2649 | */ | 2662 | */ |
2650 | if (vma->vm_ops->page_mkwrite) { | 2663 | if (vma->vm_ops->page_mkwrite) { |
2664 | int tmp; | ||
2665 | |||
2651 | unlock_page(page); | 2666 | unlock_page(page); |
2652 | if (vma->vm_ops->page_mkwrite(vma, page) < 0) { | 2667 | vmf.flags |= FAULT_FLAG_MKWRITE; |
2653 | ret = VM_FAULT_SIGBUS; | 2668 | tmp = vma->vm_ops->page_mkwrite(vma, &vmf); |
2669 | if (unlikely(tmp & | ||
2670 | (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) { | ||
2671 | ret = tmp; | ||
2654 | anon = 1; /* no anon but release vmf.page */ | 2672 | anon = 1; /* no anon but release vmf.page */ |
2655 | goto out_unlocked; | 2673 | goto out_unlocked; |
2656 | } | 2674 | } |