diff options
author | Ross Zwisler <ross.zwisler@linux.intel.com> | 2016-02-27 14:01:13 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2016-02-27 14:01:16 -0500 |
commit | 1e9d180ba39f42e8ca4a808baef3a3ef034b1c2c (patch) | |
tree | 130440fffa2025bff83c906f797afbb395529e00 | |
parent | 74dae4278546b897eb81784fdfcce872ddd8b2b8 (diff) |
ext2, ext4: fix issue with missing journal entry in ext4_dax_mkwrite()
As it is currently written ext4_dax_mkwrite() assumes that the call into
__dax_mkwrite() will not have to do a block allocation so it doesn't create
a journal entry. For a read that creates a zero page to cover a hole
followed by a write that actually allocates storage this is incorrect. The
ext4_dax_mkwrite() -> __dax_mkwrite() -> __dax_fault() path calls
get_blocks() to allocate storage.
Fix this by having the ->page_mkwrite fault handler call ext4_dax_fault()
as this function already has all the logic needed to allocate a journal
entry and call __dax_fault().
Also update the ext2 fault handlers in this same way to remove duplicate
code and keep the logic between ext2 and ext4 the same.
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | fs/ext2/file.c | 19 | ||||
-rw-r--r-- | fs/ext4/file.c | 19 |
2 files changed, 3 insertions, 35 deletions
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 2c88d683cd91..c1400b109805 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
@@ -80,23 +80,6 @@ static int ext2_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, | |||
80 | return ret; | 80 | return ret; |
81 | } | 81 | } |
82 | 82 | ||
83 | static int ext2_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
84 | { | ||
85 | struct inode *inode = file_inode(vma->vm_file); | ||
86 | struct ext2_inode_info *ei = EXT2_I(inode); | ||
87 | int ret; | ||
88 | |||
89 | sb_start_pagefault(inode->i_sb); | ||
90 | file_update_time(vma->vm_file); | ||
91 | down_read(&ei->dax_sem); | ||
92 | |||
93 | ret = __dax_mkwrite(vma, vmf, ext2_get_block, NULL); | ||
94 | |||
95 | up_read(&ei->dax_sem); | ||
96 | sb_end_pagefault(inode->i_sb); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma, | 83 | static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma, |
101 | struct vm_fault *vmf) | 84 | struct vm_fault *vmf) |
102 | { | 85 | { |
@@ -124,7 +107,7 @@ static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma, | |||
124 | static const struct vm_operations_struct ext2_dax_vm_ops = { | 107 | static const struct vm_operations_struct ext2_dax_vm_ops = { |
125 | .fault = ext2_dax_fault, | 108 | .fault = ext2_dax_fault, |
126 | .pmd_fault = ext2_dax_pmd_fault, | 109 | .pmd_fault = ext2_dax_pmd_fault, |
127 | .page_mkwrite = ext2_dax_mkwrite, | 110 | .page_mkwrite = ext2_dax_fault, |
128 | .pfn_mkwrite = ext2_dax_pfn_mkwrite, | 111 | .pfn_mkwrite = ext2_dax_pfn_mkwrite, |
129 | }; | 112 | }; |
130 | 113 | ||
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 474f1a4d2ca8..4cd318f31cbe 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -262,23 +262,8 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, | |||
262 | return result; | 262 | return result; |
263 | } | 263 | } |
264 | 264 | ||
265 | static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
266 | { | ||
267 | int err; | ||
268 | struct inode *inode = file_inode(vma->vm_file); | ||
269 | |||
270 | sb_start_pagefault(inode->i_sb); | ||
271 | file_update_time(vma->vm_file); | ||
272 | down_read(&EXT4_I(inode)->i_mmap_sem); | ||
273 | err = __dax_mkwrite(vma, vmf, ext4_dax_mmap_get_block, NULL); | ||
274 | up_read(&EXT4_I(inode)->i_mmap_sem); | ||
275 | sb_end_pagefault(inode->i_sb); | ||
276 | |||
277 | return err; | ||
278 | } | ||
279 | |||
280 | /* | 265 | /* |
281 | * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_mkwrite() | 266 | * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_fault() |
282 | * handler we check for races agaist truncate. Note that since we cycle through | 267 | * handler we check for races agaist truncate. Note that since we cycle through |
283 | * i_mmap_sem, we are sure that also any hole punching that began before we | 268 | * i_mmap_sem, we are sure that also any hole punching that began before we |
284 | * were called is finished by now and so if it included part of the file we | 269 | * were called is finished by now and so if it included part of the file we |
@@ -311,7 +296,7 @@ static int ext4_dax_pfn_mkwrite(struct vm_area_struct *vma, | |||
311 | static const struct vm_operations_struct ext4_dax_vm_ops = { | 296 | static const struct vm_operations_struct ext4_dax_vm_ops = { |
312 | .fault = ext4_dax_fault, | 297 | .fault = ext4_dax_fault, |
313 | .pmd_fault = ext4_dax_pmd_fault, | 298 | .pmd_fault = ext4_dax_pmd_fault, |
314 | .page_mkwrite = ext4_dax_mkwrite, | 299 | .page_mkwrite = ext4_dax_fault, |
315 | .pfn_mkwrite = ext4_dax_pfn_mkwrite, | 300 | .pfn_mkwrite = ext4_dax_pfn_mkwrite, |
316 | }; | 301 | }; |
317 | #else | 302 | #else |