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 | |
| 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>
| -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 = { |
