summaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorMaxim Patlasov <MPatlasov@parallels.com>2014-02-20 16:58:05 -0500
committerTheodore Ts'o <tytso@mit.edu>2014-02-20 16:58:05 -0500
commite251f9bca99c0f219eff9c76034476c2b17d3dba (patch)
tree413d9b1af6fd9b916c0bdb9f7380d5657c093efb /fs/ext4/inode.c
parentce140cdd9c171dc75cfdcfee2b8708c508f5daf6 (diff)
ext4: avoid exposure of stale data in ext4_punch_hole()
While handling punch-hole fallocate, it's useless to truncate page cache before removing the range from extent tree (or block map in indirect case) because page cache can be re-populated (by read-ahead or read(2) or mmap-ed read) immediately after truncating page cache, but before updating extent tree (or block map). In that case the user will see stale data even after fallocate is completed. Until the problem of data corruption resulting from pages backed by already freed blocks is fully resolved, the simple thing we can do now is to add another truncation of pagecache after punch hole is done. Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 113458c9d08b..5324a38d848d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3614,6 +3614,12 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
3614 up_write(&EXT4_I(inode)->i_data_sem); 3614 up_write(&EXT4_I(inode)->i_data_sem);
3615 if (IS_SYNC(inode)) 3615 if (IS_SYNC(inode))
3616 ext4_handle_sync(handle); 3616 ext4_handle_sync(handle);
3617
3618 /* Now release the pages again to reduce race window */
3619 if (last_block_offset > first_block_offset)
3620 truncate_pagecache_range(inode, first_block_offset,
3621 last_block_offset);
3622
3617 inode->i_mtime = inode->i_ctime = ext4_current_time(inode); 3623 inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
3618 ext4_mark_inode_dirty(handle, inode); 3624 ext4_mark_inode_dirty(handle, inode);
3619out_stop: 3625out_stop: