ocfs2/dlm: Remove BUG_ON in dlm recovery when freeing locks of a dead node
[safe/jmp/linux-2.6] / fs / ocfs2 / mmap.c
index d79aa12..3973761 100644 (file)
@@ -60,31 +60,28 @@ static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
        return sigprocmask(SIG_SETMASK, oldset, NULL);
 }
 
-static struct page *ocfs2_nopage(struct vm_area_struct * area,
-                                unsigned long address,
-                                int *type)
+static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
 {
-       struct page *page = NOPAGE_SIGBUS;
        sigset_t blocked, oldset;
-       int ret;
+       int error, ret;
 
-       mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address,
-                  type);
+       mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff);
 
-       ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
-       if (ret < 0) {
-               mlog_errno(ret);
+       error = ocfs2_vm_op_block_sigs(&blocked, &oldset);
+       if (error < 0) {
+               mlog_errno(error);
+               ret = VM_FAULT_SIGBUS;
                goto out;
        }
 
-       page = filemap_nopage(area, address, type);
+       ret = filemap_fault(area, vmf);
 
-       ret = ocfs2_vm_op_unblock_sigs(&oldset);
-       if (ret < 0)
-               mlog_errno(ret);
+       error = ocfs2_vm_op_unblock_sigs(&oldset);
+       if (error < 0)
+               mlog_errno(error);
 out:
-       mlog_exit_ptr(page);
-       return page;
+       mlog_exit_ptr(vmf->page);
+       return ret;
 }
 
 static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
@@ -92,7 +89,7 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
 {
        int ret;
        struct address_space *mapping = inode->i_mapping;
-       loff_t pos = page->index << PAGE_CACHE_SHIFT;
+       loff_t pos = page_offset(page);
        unsigned int len = PAGE_CACHE_SIZE;
        pgoff_t last_index;
        struct page *locked_page = NULL;
@@ -116,7 +113,11 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
         * ocfs2_write_begin_nolock().
         */
        if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
-               ret = -EINVAL;
+               /*
+                * the page has been umapped in ocfs2_data_downconvert_worker.
+                * So return 0 here and let VFS retry.
+                */
+               ret = 0;
                goto out;
        }
 
@@ -153,8 +154,9 @@ out:
        return ret;
 }
 
-static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
+       struct page *page = vmf->page;
        struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
        struct buffer_head *di_bh = NULL;
        sigset_t blocked, oldset;
@@ -171,7 +173,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
         * node. Taking the data lock will also ensure that we don't
         * attempt page truncation as part of a downconvert.
         */
-       ret = ocfs2_meta_lock(inode, &di_bh, 1);
+       ret = ocfs2_inode_lock(inode, &di_bh, 1);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -184,32 +186,24 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
         */
        down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-       ret = ocfs2_data_lock(inode, 1);
-       if (ret < 0) {
-               mlog_errno(ret);
-               goto out_meta_unlock;
-       }
-
        ret = __ocfs2_page_mkwrite(inode, di_bh, page);
 
-       ocfs2_data_unlock(inode, 1);
-
-out_meta_unlock:
        up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
        brelse(di_bh);
-       ocfs2_meta_unlock(inode, 1);
+       ocfs2_inode_unlock(inode, 1);
 
 out:
        ret2 = ocfs2_vm_op_unblock_sigs(&oldset);
        if (ret2 < 0)
                mlog_errno(ret2);
-
+       if (ret)
+               ret = VM_FAULT_SIGBUS;
        return ret;
 }
 
-static struct vm_operations_struct ocfs2_file_vm_ops = {
-       .nopage         = ocfs2_nopage,
+static const struct vm_operations_struct ocfs2_file_vm_ops = {
+       .fault          = ocfs2_fault,
        .page_mkwrite   = ocfs2_page_mkwrite,
 };
 
@@ -217,15 +211,16 @@ int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
        int ret = 0, lock_level = 0;
 
-       ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode,
+       ret = ocfs2_inode_lock_atime(file->f_dentry->d_inode,
                                    file->f_vfsmnt, &lock_level);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
        }
-       ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level);
+       ocfs2_inode_unlock(file->f_dentry->d_inode, lock_level);
 out:
        vma->vm_ops = &ocfs2_file_vm_ops;
+       vma->vm_flags |= VM_CAN_NONLINEAR;
        return 0;
 }