diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2013-10-01 10:44:51 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-10-01 10:44:51 -0400 |
commit | cca2437045dda994d23bd65891b71e091fa35b5a (patch) | |
tree | 6eee39d3226134edf8c9d68ce381668542b9a915 /fs/fuse | |
parent | 385b126815d9278cf347504cf17ba62fb57e00ca (diff) |
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) | |||
1618 | static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | 1618 | static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
1619 | { | 1619 | { |
1620 | struct page *page = vmf->page; | 1620 | struct page *page = vmf->page; |
1621 | /* | 1621 | struct inode *inode = file_inode(vma->vm_file); |
1622 | * Don't use page->mapping as it may become NULL from a | 1622 | |
1623 | * concurrent truncate. | 1623 | file_update_time(vma->vm_file); |
1624 | */ | 1624 | lock_page(page); |
1625 | struct inode *inode = vma->vm_file->f_mapping->host; | 1625 | if (page->mapping != inode->i_mapping) { |
1626 | unlock_page(page); | ||
1627 | return VM_FAULT_NOPAGE; | ||
1628 | } | ||
1626 | 1629 | ||
1627 | fuse_wait_on_page_writeback(inode, page->index); | 1630 | fuse_wait_on_page_writeback(inode, page->index); |
1628 | return 0; | 1631 | return VM_FAULT_LOCKED; |
1629 | } | 1632 | } |
1630 | 1633 | ||
1631 | static const struct vm_operations_struct fuse_file_vm_ops = { | 1634 | static const struct vm_operations_struct fuse_file_vm_ops = { |