update commit description for fix-memleak-in-ext4_readdir
[ext4-patch-queue.git] / fix-crashes-in-dioread_nolock-mode
blob9fd89dfe86ac9ae0c8f526f2e972aa29deb2e187
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
15 later.
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>
20 ---
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
26 --- a/fs/ext4/inode.c
27 +++ b/fs/ext4/inode.c
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.
30          */
31         iocb->private = NULL;
32 -       ext4_inode_aio_set(inode, NULL);
33 -       if (!is_sync_kiocb(iocb)) {
34 -               io_end = ext4_init_io_end(inode, GFP_NOFS);
35 -               if (!io_end) {
36 -                       ret = -ENOMEM;
37 -                       goto retake_lock;
38 -               }
39 -               /*
40 -                * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
41 -                */
42 -               iocb->private = ext4_get_io_end(io_end);
43 -               /*
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.
48 -                */
49 -               ext4_inode_aio_set(inode, io_end);
50 -       }
52         if (overwrite) {
53                 get_block_func = ext4_get_block_overwrite;
54         } else {
55 +               ext4_inode_aio_set(inode, NULL);
56 +               if (!is_sync_kiocb(iocb)) {
57 +                       io_end = ext4_init_io_end(inode, GFP_NOFS);
58 +                       if (!io_end) {
59 +                               ret = -ENOMEM;
60 +                               goto retake_lock;
61 +                       }
62 +                       /*
63 +                        * Grab reference for DIO. Will be dropped in
64 +                        * ext4_end_io_dio()
65 +                        */
66 +                       iocb->private = ext4_get_io_end(io_end);
67 +                       /*
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.
72 +                        */
73 +                       ext4_inode_aio_set(inode, io_end);
74 +               }
75                 get_block_func = ext4_get_block_write;
76                 dio_flags = DIO_LOCKING;
77         }
78 -- 
79 2.6.2