summaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2013-10-01 16:44:51 +0200
committerMiklos Szeredi <mszeredi@suse.cz>2013-10-01 16:44:51 +0200
commitcca2437045dda994d23bd65891b71e091fa35b5a (patch)
tree6eee39d3226134edf8c9d68ce381668542b9a915 /fs/fuse
parentfuse: Prepare to handle multiple pages in writeback (diff)
downloadlinux-cca2437045dda994d23bd65891b71e091fa35b5a.tar.xz
linux-cca2437045dda994d23bd65891b71e091fa35b5a.zip
fuse: lock page in mkwrite
Lock the page in fuse_page_mkwrite() to protect against a race with fuse_writepage() where the page is redirtied before the actual writeback begins. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/file.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 944acc096752..6fb9425c23c6 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1618,14 +1618,17 @@ static void fuse_vma_close(struct vm_area_struct *vma)
static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct page *page = vmf->page;
- /*
- * Don't use page->mapping as it may become NULL from a
- * concurrent truncate.
- */
- struct inode *inode = vma->vm_file->f_mapping->host;
+ struct inode *inode = file_inode(vma->vm_file);
+
+ file_update_time(vma->vm_file);
+ lock_page(page);
+ if (page->mapping != inode->i_mapping) {
+ unlock_page(page);
+ return VM_FAULT_NOPAGE;
+ }
fuse_wait_on_page_writeback(inode, page->index);
- return 0;
+ return VM_FAULT_LOCKED;
}
static const struct vm_operations_struct fuse_file_vm_ops = {