FAILED: patch "[PATCH] ext4: fix crashes in dioread_nolock mode" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
74dae4278546b897eb81784fdfcce872ddd8b2b8Mon Sep 17 00:00:00 2001
From: Jan Kara <[email protected]>
Date: Fri, 19 Feb 2016 00:33:21 -0500
Subject: [PATCH] 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.
fs/ext4/inode.c +20 -20
@@ -3281,29 +3281,29 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,* 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_overwrite; }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 ; }