diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2013-10-01 16:44:51 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-10-01 16:44:51 +0200 |
commit | cca2437045dda994d23bd65891b71e091fa35b5a (patch) | |
tree | 6eee39d3226134edf8c9d68ce381668542b9a915 /fs/fuse | |
parent | fuse: Prepare to handle multiple pages in writeback (diff) | |
download | linux-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.c | 15 |
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 = { |