xfs: pulling read IO path locking up to protect S_DAX checks From: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_file.c | 77 +++++++++++++++++-------------------------------------- 1 file changed, 24 insertions(+), 53 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index b8a4a3f29b36..7d31a0e76b68 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -176,28 +176,12 @@ xfs_file_dio_aio_read( struct kiocb *iocb, struct iov_iter *to) { - struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp)); - size_t count = iov_iter_count(to); - ssize_t ret; - - trace_xfs_file_direct_read(ip, count, iocb->ki_pos); - - if (!count) - return 0; /* skip atime */ + trace_xfs_file_direct_read(XFS_I(file_inode(iocb->ki_filp)), + iov_iter_count(to), iocb->ki_pos); file_accessed(iocb->ki_filp); - - if (iocb->ki_flags & IOCB_NOWAIT) { - if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) - return -EAGAIN; - } else { - xfs_ilock(ip, XFS_IOLOCK_SHARED); - } - ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, + return iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, is_sync_kiocb(iocb)); - xfs_iunlock(ip, XFS_IOLOCK_SHARED); - - return ret; } static noinline ssize_t @@ -205,27 +189,12 @@ xfs_file_dax_read( struct kiocb *iocb, struct iov_iter *to) { - struct xfs_inode *ip = XFS_I(iocb->ki_filp->f_mapping->host); - size_t count = iov_iter_count(to); - ssize_t ret = 0; - - trace_xfs_file_dax_read(ip, count, iocb->ki_pos); - - if (!count) - return 0; /* skip atime */ - - if (iocb->ki_flags & IOCB_NOWAIT) { - if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) - return -EAGAIN; - } else { - xfs_ilock(ip, XFS_IOLOCK_SHARED); - } - - ret = dax_iomap_rw(iocb, to, &xfs_read_iomap_ops); - xfs_iunlock(ip, XFS_IOLOCK_SHARED); + trace_xfs_file_dax_read(XFS_I(file_inode(iocb->ki_filp)), + iov_iter_count(to), iocb->ki_pos); file_accessed(iocb->ki_filp); - return ret; + return dax_iomap_rw(iocb, to, &xfs_read_iomap_ops); + } STATIC ssize_t @@ -233,21 +202,10 @@ xfs_file_buffered_aio_read( struct kiocb *iocb, struct iov_iter *to) { - struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp)); - ssize_t ret; - - trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); + trace_xfs_file_buffered_read(XFS_I(file_inode(iocb->ki_filp)), + iov_iter_count(to), iocb->ki_pos); - if (iocb->ki_flags & IOCB_NOWAIT) { - if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) - return -EAGAIN; - } else { - xfs_ilock(ip, XFS_IOLOCK_SHARED); - } - ret = generic_file_read_iter(iocb, to); - xfs_iunlock(ip, XFS_IOLOCK_SHARED); - - return ret; + return generic_file_read_iter(iocb, to); } STATIC ssize_t @@ -256,7 +214,8 @@ xfs_file_read_iter( struct iov_iter *to) { struct inode *inode = file_inode(iocb->ki_filp); - struct xfs_mount *mp = XFS_I(inode)->i_mount; + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; ssize_t ret = 0; XFS_STATS_INC(mp, xs_read_calls); @@ -264,6 +223,16 @@ xfs_file_read_iter( if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; + if (!iov_iter_count(to)) + return 0; /* skip atime */ + + if (iocb->ki_flags & IOCB_NOWAIT) { + if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) + return -EAGAIN; + } else { + xfs_ilock(ip, XFS_IOLOCK_SHARED); + } + if (IS_DAX(inode)) ret = xfs_file_dax_read(iocb, to); else if (iocb->ki_flags & IOCB_DIRECT) @@ -271,6 +240,8 @@ xfs_file_read_iter( else ret = xfs_file_buffered_aio_read(iocb, to); + xfs_iunlock(ip, XFS_IOLOCK_SHARED); + if (ret > 0) XFS_STATS_ADD(mp, xs_read_bytes, ret); return ret;