aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-10-02 18:48:08 -0400
committerDave Chinner <david@fromorbit.com>2016-10-02 18:48:08 -0400
commit0d5b0cf246a3227d811e7bf55d756b273408e414 (patch)
tree08163c5359913d1747cc2ef74394b313c0949cbd
parenta447d7cd15c759d8ab7f3c9c8183aa8c999d7ed4 (diff)
fs: update atime before I/O in generic_file_read_iter
After the call to ->direct_IO the final reference to the file might have been dropped by aio_complete already, and the call to file_accessed might cause a use after free. Instead update the access time before the I/O, similar to how we update the time stamps before writes. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--mm/filemap.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 8a287dfc5372..2f1175e86c77 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1910,16 +1910,18 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
1910 if (iocb->ki_flags & IOCB_DIRECT) { 1910 if (iocb->ki_flags & IOCB_DIRECT) {
1911 struct address_space *mapping = file->f_mapping; 1911 struct address_space *mapping = file->f_mapping;
1912 struct inode *inode = mapping->host; 1912 struct inode *inode = mapping->host;
1913 struct iov_iter data = *iter;
1913 loff_t size; 1914 loff_t size;
1914 1915
1915 size = i_size_read(inode); 1916 size = i_size_read(inode);
1916 retval = filemap_write_and_wait_range(mapping, iocb->ki_pos, 1917 retval = filemap_write_and_wait_range(mapping, iocb->ki_pos,
1917 iocb->ki_pos + count - 1); 1918 iocb->ki_pos + count - 1);
1918 if (!retval) { 1919 if (retval < 0)
1919 struct iov_iter data = *iter; 1920 goto out;
1920 retval = mapping->a_ops->direct_IO(iocb, &data);
1921 }
1922 1921
1922 file_accessed(file);
1923
1924 retval = mapping->a_ops->direct_IO(iocb, &data);
1923 if (retval > 0) { 1925 if (retval > 0) {
1924 iocb->ki_pos += retval; 1926 iocb->ki_pos += retval;
1925 iov_iter_advance(iter, retval); 1927 iov_iter_advance(iter, retval);
@@ -1935,10 +1937,8 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
1935 * DAX files, so don't bother trying. 1937 * DAX files, so don't bother trying.
1936 */ 1938 */
1937 if (retval < 0 || !iov_iter_count(iter) || iocb->ki_pos >= size || 1939 if (retval < 0 || !iov_iter_count(iter) || iocb->ki_pos >= size ||
1938 IS_DAX(inode)) { 1940 IS_DAX(inode))
1939 file_accessed(file);
1940 goto out; 1941 goto out;
1941 }
1942 } 1942 }
1943 1943
1944 retval = do_generic_file_read(file, &iocb->ki_pos, iter, retval); 1944 retval = do_generic_file_read(file, &iocb->ki_pos, iter, retval);