]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/gfs2/ops_vm.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh64-2.6
[linux-2.6-omap-h63xx.git] / fs / gfs2 / ops_vm.c
index 14b380fb060290a77f24a96872e8b6b439707128..927d739d468512502225331857c859bf05d826ca 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include "trans.h"
 #include "util.h"
 
-static struct page *gfs2_private_nopage(struct vm_area_struct *area,
-                                       unsigned long address, int *type)
+static int gfs2_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-       struct gfs2_inode *ip = GFS2_I(area->vm_file->f_mapping->host);
+       struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host);
 
        set_bit(GIF_PAGED, &ip->i_flags);
-       return filemap_nopage(area, address, type);
+       return filemap_fault(vma, vmf);
 }
 
 static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
@@ -67,7 +65,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
        if (error)
                goto out_gunlock_q;
 
-       error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length +
+       error = gfs2_trans_begin(sdp, al->al_rgd->rd_length +
                                 ind_blocks + RES_DINODE +
                                 RES_STATFS + RES_QUOTA, 0);
        if (error)
@@ -105,58 +103,67 @@ out:
        return error;
 }
 
-static struct page *gfs2_sharewrite_nopage(struct vm_area_struct *area,
-                                          unsigned long address, int *type)
+static int gfs2_sharewrite_fault(struct vm_area_struct *vma,
+                                               struct vm_fault *vmf)
 {
-       struct file *file = area->vm_file;
+       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;
-       unsigned long index = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) +
-                             area->vm_pgoff;
        int alloc_required;
        int error;
+       int ret = 0;
 
        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)index << PAGE_CACHE_SHIFT,
-                                         PAGE_CACHE_SIZE, &alloc_required);
-       if (error)
-               goto out;
+       error = gfs2_write_alloc_required(ip,
+                                       (u64)vmf->pgoff << PAGE_CACHE_SHIFT,
+                                       PAGE_CACHE_SIZE, &alloc_required);
+       if (error) {
+               ret = VM_FAULT_OOM; /* XXX: are these right? */
+               goto out_unlock;
+       }
 
        set_bit(GFF_EXLOCK, &gf->f_flags);
-       result = filemap_nopage(area, address, type);
+       ret = filemap_fault(vma, vmf);
        clear_bit(GFF_EXLOCK, &gf->f_flags);
-       if (!result || result == NOPAGE_OOM)
-               goto out;
+       if (ret & VM_FAULT_ERROR)
+               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) {
-                       page_cache_release(result);
-                       result = NULL;
-                       goto out;
+                       /*
+                        * VM_FAULT_LOCKED should always be the case for
+                        * filemap_fault, but it may not be in a future
+                        * implementation.
+                        */
+                       if (ret & VM_FAULT_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 = {
-       .nopage = gfs2_private_nopage,
+       .fault = gfs2_private_fault,
 };
 
 struct vm_operations_struct gfs2_vm_ops_sharewrite = {
-       .nopage = gfs2_sharewrite_nopage,
+       .fault = gfs2_sharewrite_fault,
 };