aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2009-03-31 18:23:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-01 11:59:14 -0400
commitc2ec175c39f62949438354f603f4aa170846aabb (patch)
treef2c9bf1bec2deabe2d3a5092405b027637b6ead3 /mm/memory.c
parentc2fdf3a9b2d52842808a8e551b53b55dd9b45030 (diff)
mm: page_mkwrite change prototype to match fault
Change the page_mkwrite prototype to take a struct vm_fault, and return VM_FAULT_xxx flags. There should be no functional change. This makes it possible to return much more detailed error information to the VM (and also can provide more information eg. virtual_address to the driver, which might be important in some special cases). This is required for a subsequent fix. And will also make it easier to merge page_mkwrite() with fault() in future. Signed-off-by: Nick Piggin <npiggin@suse.de> Cc: Chris Mason <chris.mason@oracle.com> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: Steven Whitehouse <swhiteho@redhat.com> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Joel Becker <joel.becker@oracle.com> Cc: Artem Bityutskiy <dedekind@infradead.org> Cc: Felix Blyakher <felixb@sgi.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.c26
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
2107unwritable_page: 2120unwritable_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 }