diff options
author | Nick Piggin <npiggin@suse.de> | 2007-07-19 01:47:03 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 10:04:41 -0700 |
commit | d0217ac04ca6591841e5665f518e38064f4e65bd (patch) | |
tree | d3309094bb734d34773f97d642593e298a5cfcfc /fs/gfs2/ops_vm.c | |
parent | ed2f2f9b3ff8debdf512f7687b232c3c1d7d60d7 (diff) |
mm: fault feedback #1
Change ->fault prototype. We now return an int, which contains
VM_FAULT_xxx code in the low byte, and FAULT_RET_xxx code in the next byte.
FAULT_RET_ code tells the VM whether a page was found, whether it has been
locked, and potentially other things. This is not quite the way he wanted
it yet, but that's changed in the next patch (which requires changes to
arch code).
This means we no longer set VM_CAN_INVALIDATE in the vma in order to say
that a page is locked which requires filemap_nopage to go away (because we
can no longer remain backward compatible without that flag), but we were
going to do that anyway.
struct fault_data is renamed to struct vm_fault as Linus asked. address
is now a void __user * that we should firmly encourage drivers not to use
without really good reason.
The page is now returned via a page pointer in the vm_fault struct.
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/gfs2/ops_vm.c')
-rw-r--r-- | fs/gfs2/ops_vm.c | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c index e9fe6eb74e7..dc287d2e3a6 100644 --- a/fs/gfs2/ops_vm.c +++ b/fs/gfs2/ops_vm.c @@ -27,13 +27,12 @@ #include "trans.h" #include "util.h" -static struct page *gfs2_private_fault(struct vm_area_struct *vma, - struct fault_data *fdata) +static int gfs2_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host); set_bit(GIF_PAGED, &ip->i_flags); - return filemap_fault(vma, fdata); + return filemap_fault(vma, vmf); } static int alloc_page_backing(struct gfs2_inode *ip, struct page *page) @@ -104,55 +103,55 @@ out: return error; } -static struct page *gfs2_sharewrite_fault(struct vm_area_struct *vma, - struct fault_data *fdata) +static int gfs2_sharewrite_fault(struct vm_area_struct *vma, + struct vm_fault *vmf) { struct file *file = vma->vm_file; struct gfs2_file *gf = file->private_data; struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); struct gfs2_holder i_gh; - struct page *result = NULL; int alloc_required; int error; + int ret = VM_FAULT_MINOR; error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); if (error) - return NULL; + goto out; set_bit(GIF_PAGED, &ip->i_flags); set_bit(GIF_SW_PAGED, &ip->i_flags); error = gfs2_write_alloc_required(ip, - (u64)fdata->pgoff << PAGE_CACHE_SHIFT, + (u64)vmf->pgoff << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE, &alloc_required); if (error) { - fdata->type = VM_FAULT_OOM; /* XXX: are these right? */ - goto out; + ret = VM_FAULT_OOM; /* XXX: are these right? */ + goto out_unlock; } set_bit(GFF_EXLOCK, &gf->f_flags); - result = filemap_fault(vma, fdata); + ret = filemap_fault(vma, vmf); clear_bit(GFF_EXLOCK, &gf->f_flags); - if (!result) - goto out; + if (ret & (VM_FAULT_ERROR | FAULT_RET_NOPAGE)) + goto out_unlock; if (alloc_required) { - error = alloc_page_backing(ip, result); + /* XXX: do we need to drop page lock around alloc_page_backing?*/ + error = alloc_page_backing(ip, vmf->page); if (error) { - if (vma->vm_flags & VM_CAN_INVALIDATE) - unlock_page(result); - page_cache_release(result); - fdata->type = VM_FAULT_OOM; - result = NULL; - goto out; + if (ret & FAULT_RET_LOCKED) + unlock_page(vmf->page); + page_cache_release(vmf->page); + ret = VM_FAULT_OOM; + goto out_unlock; } - set_page_dirty(result); + set_page_dirty(vmf->page); } -out: +out_unlock: gfs2_glock_dq_uninit(&i_gh); - - return result; +out: + return ret; } struct vm_operations_struct gfs2_vm_ops_private = { |