Skip to content

Commit

Permalink
NFS: Don't SIGBUS if nfs_vm_page_mkwrite races with a cache invalidation
Browse files Browse the repository at this point in the history
commit bc4866b upstream.

In the case where we lock the page, and then find out that the page has
been thrown out of the page cache, we should just return VM_FAULT_NOPAGE.
This is what block_page_mkwrite() does in these situations.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
  • Loading branch information
Trond Myklebust authored and Andi Kleen committed Dec 14, 2010
1 parent 7c1f052 commit babbccf
Showing 1 changed file with 8 additions and 9 deletions.
17 changes: 8 additions & 9 deletions fs/nfs/file.c
Expand Up @@ -560,7 +560,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
struct file *filp = vma->vm_file;
struct dentry *dentry = filp->f_path.dentry;
unsigned pagelen;
int ret = -EINVAL;
int ret = VM_FAULT_NOPAGE;
struct address_space *mapping;

dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n",
Expand All @@ -576,21 +576,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
if (mapping != dentry->d_inode->i_mapping)
goto out_unlock;

ret = 0;
pagelen = nfs_page_length(page);
if (pagelen == 0)
goto out_unlock;

ret = nfs_flush_incompatible(filp, page);
if (ret != 0)
goto out_unlock;
ret = VM_FAULT_LOCKED;
if (nfs_flush_incompatible(filp, page) == 0 &&
nfs_updatepage(filp, page, 0, pagelen) == 0)
goto out;

ret = nfs_updatepage(filp, page, 0, pagelen);
ret = VM_FAULT_SIGBUS;
out_unlock:
if (!ret)
return VM_FAULT_LOCKED;
unlock_page(page);
return VM_FAULT_SIGBUS;
out:
return ret;
}

static const struct vm_operations_struct nfs_file_vm_ops = {
Expand Down

0 comments on commit babbccf

Please sign in to comment.