diff options
author | Christoph Hellwig <hch@lst.de> | 2016-10-02 18:48:08 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-10-02 18:48:08 -0400 |
commit | 0d5b0cf246a3227d811e7bf55d756b273408e414 (patch) | |
tree | 08163c5359913d1747cc2ef74394b313c0949cbd | |
parent | a447d7cd15c759d8ab7f3c9c8183aa8c999d7ed4 (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.c | 14 |
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); |