aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2016-02-19 00:33:21 -0500
committerTheodore Ts'o <tytso@mit.edu>2016-02-19 00:33:21 -0500
commit74dae4278546b897eb81784fdfcce872ddd8b2b8 (patch)
tree1f8933f3ec2715cdfcbac993cf0409e884caf11c
parented8ad83808f009ade97ebbf6519bc3a97fefbc0c (diff)
ext4: fix crashes in dioread_nolock mode
Competing overwrite DIO in dioread_nolock mode will just overwrite pointer to io_end in the inode. This may result in data corruption or extent conversion happening from IO completion interrupt because we don't properly set buffer_defer_completion() when unlocked DIO races with locked DIO to unwritten extent. Since unlocked DIO doesn't need io_end for anything, just avoid allocating it and corrupting pointer from inode for locked DIO. A cleaner fix would be to avoid these games with io_end pointer from the inode but that requires more intrusive changes so we leave that for later. Cc: stable@vger.kernel.org Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/inode.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index d6674479269d..9cc57c3b4661 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3281,29 +3281,29 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
3281 * case, we allocate an io_end structure to hook to the iocb. 3281 * case, we allocate an io_end structure to hook to the iocb.
3282 */ 3282 */
3283 iocb->private = NULL; 3283 iocb->private = NULL;
3284 ext4_inode_aio_set(inode, NULL);
3285 if (!is_sync_kiocb(iocb)) {
3286 io_end = ext4_init_io_end(inode, GFP_NOFS);
3287 if (!io_end) {
3288 ret = -ENOMEM;
3289 goto retake_lock;
3290 }
3291 /*
3292 * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
3293 */
3294 iocb->private = ext4_get_io_end(io_end);
3295 /*
3296 * we save the io structure for current async direct
3297 * IO, so that later ext4_map_blocks() could flag the
3298 * io structure whether there is a unwritten extents
3299 * needs to be converted when IO is completed.
3300 */
3301 ext4_inode_aio_set(inode, io_end);
3302 }
3303
3304 if (overwrite) { 3284 if (overwrite) {
3305 get_block_func = ext4_get_block_overwrite; 3285 get_block_func = ext4_get_block_overwrite;
3306 } else { 3286 } else {
3287 ext4_inode_aio_set(inode, NULL);
3288 if (!is_sync_kiocb(iocb)) {
3289 io_end = ext4_init_io_end(inode, GFP_NOFS);
3290 if (!io_end) {
3291 ret = -ENOMEM;
3292 goto retake_lock;
3293 }
3294 /*
3295 * Grab reference for DIO. Will be dropped in
3296 * ext4_end_io_dio()
3297 */
3298 iocb->private = ext4_get_io_end(io_end);
3299 /*
3300 * we save the io structure for current async direct
3301 * IO, so that later ext4_map_blocks() could flag the
3302 * io structure whether there is a unwritten extents
3303 * needs to be converted when IO is completed.
3304 */
3305 ext4_inode_aio_set(inode, io_end);
3306 }
3307 get_block_func = ext4_get_block_write; 3307 get_block_func = ext4_get_block_write;
3308 dio_flags = DIO_LOCKING; 3308 dio_flags = DIO_LOCKING;
3309 } 3309 }