lkml.org 
[lkml]   [2016]   [Mar]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.19.y-ckt 129/196] ext4: fix crashes in dioread_nolock mode
    Date
    3.19.8-ckt16 -stable review patch.  If anyone has any objections, please let me know.

    ---8<------------------------------------------------------------

    From: Jan Kara <jack@suse.cz>

    commit 74dae4278546b897eb81784fdfcce872ddd8b2b8 upstream.

    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.

    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Theodore Ts'o <tytso@mit.edu>
    Signed-off-by: Kamal Mostafa <kamal@canonical.com>
    ---
    fs/ext4/inode.c | 40 ++++++++++++++++++++--------------------
    1 file changed, 20 insertions(+), 20 deletions(-)

    diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
    index dc1833e..77c8ce1 100644
    --- a/fs/ext4/inode.c
    +++ b/fs/ext4/inode.c
    @@ -3038,29 +3038,29 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
    * case, we allocate an io_end structure to hook to the iocb.
    */
    iocb->private = NULL;
    - ext4_inode_aio_set(inode, NULL);
    - if (!is_sync_kiocb(iocb)) {
    - io_end = ext4_init_io_end(inode, GFP_NOFS);
    - if (!io_end) {
    - ret = -ENOMEM;
    - goto retake_lock;
    - }
    - /*
    - * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
    - */
    - iocb->private = ext4_get_io_end(io_end);
    - /*
    - * we save the io structure for current async direct
    - * IO, so that later ext4_map_blocks() could flag the
    - * io structure whether there is a unwritten extents
    - * needs to be converted when IO is completed.
    - */
    - ext4_inode_aio_set(inode, io_end);
    - }
    -
    if (overwrite) {
    get_block_func = ext4_get_block_write_nolock;
    } else {
    + ext4_inode_aio_set(inode, NULL);
    + if (!is_sync_kiocb(iocb)) {
    + io_end = ext4_init_io_end(inode, GFP_NOFS);
    + if (!io_end) {
    + ret = -ENOMEM;
    + goto retake_lock;
    + }
    + /*
    + * Grab reference for DIO. Will be dropped in
    + * ext4_end_io_dio()
    + */
    + iocb->private = ext4_get_io_end(io_end);
    + /*
    + * we save the io structure for current async direct
    + * IO, so that later ext4_map_blocks() could flag the
    + * io structure whether there is a unwritten extents
    + * needs to be converted when IO is completed.
    + */
    + ext4_inode_aio_set(inode, io_end);
    + }
    get_block_func = ext4_get_block_write;
    dio_flags = DIO_LOCKING;
    }
    --
    2.7.0
    \
     
     \ /
      Last update: 2016-03-09 02:41    [W:4.109 / U:0.128 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site