1 ext4: fix crashes in dioread_nolock mode
3 From: Jan Kara <jack@suse.cz>
5 Competing overwrite DIO in dioread_nolock mode will just overwrite
6 pointer to io_end in the inode. This may result in data corruption or
7 extent conversion happening from IO completion interrupt because we
8 don't properly set buffer_defer_completion() when unlocked DIO races
9 with locked DIO to unwritten extent.
11 Since unlocked DIO doesn't need io_end for anything, just avoid
12 allocating it and corrupting pointer from inode for locked DIO.
13 A cleaner fix would be to avoid these games with io_end pointer from the
14 inode but that requires more intrusive changes so we leave that for
17 Cc: stable@vger.kernel.org
18 Signed-off-by: Jan Kara <jack@suse.cz>
19 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
21 fs/ext4/inode.c | 40 ++++++++++++++++++++--------------------
22 1 file changed, 20 insertions(+), 20 deletions(-)
24 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
25 index 83bc8bfb3bea..ee8ca1ff4023 100644
28 @@ -3253,29 +3253,29 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
29 * case, we allocate an io_end structure to hook to the iocb.
32 - ext4_inode_aio_set(inode, NULL);
33 - if (!is_sync_kiocb(iocb)) {
34 - io_end = ext4_init_io_end(inode, GFP_NOFS);
40 - * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
42 - iocb->private = ext4_get_io_end(io_end);
44 - * we save the io structure for current async direct
45 - * IO, so that later ext4_map_blocks() could flag the
46 - * io structure whether there is a unwritten extents
47 - * needs to be converted when IO is completed.
49 - ext4_inode_aio_set(inode, io_end);
53 get_block_func = ext4_get_block_overwrite;
55 + ext4_inode_aio_set(inode, NULL);
56 + if (!is_sync_kiocb(iocb)) {
57 + io_end = ext4_init_io_end(inode, GFP_NOFS);
63 + * Grab reference for DIO. Will be dropped in
66 + iocb->private = ext4_get_io_end(io_end);
68 + * we save the io structure for current async direct
69 + * IO, so that later ext4_map_blocks() could flag the
70 + * io structure whether there is a unwritten extents
71 + * needs to be converted when IO is completed.
73 + ext4_inode_aio_set(inode, io_end);
75 get_block_func = ext4_get_block_write;
76 dio_flags = DIO_LOCKING;