aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2016-01-04 00:28:25 -0500
committerDave Chinner <david@fromorbit.com>2016-01-04 00:28:25 -0500
commita6d7636e8d0fd94fd1937db91d5b06a91fa85dde (patch)
tree41b326d5e1ee03a7948c692064002d18282d3fe2 /fs/xfs
parent3b0fe47805802216087259b07de691ef47ff6fbc (diff)
xfs: fix recursive splice read locking with DAX
Doing a splice read (generic/249) generates a lockdep splat because we recursively lock the inode iolock in this path: SyS_sendfile64 do_sendfile do_splice_direct splice_direct_to_actor do_splice_to xfs_file_splice_read <<<<<< lock here default_file_splice_read vfs_readv do_readv_writev do_iter_readv_writev xfs_file_read_iter <<<<<< then here The issue here is that for DAX inodes we need to avoid the page cache path and hence simply push it into the normal read path. Unfortunately, we can't tell down at xfs_file_read_iter() whether we are being called from the splice path and hence we cannot avoid the locking at this layer. Hence we simply have to drop the inode locking at the higher splice layer for DAX. Signed-off-by: Dave Chinner <dchinner@redhat.com> Tested-by: Ross Zwisler <ross.zwisler@linux.intel.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_file.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f5392ab2def1..ebe9b8290a70 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -402,19 +402,26 @@ xfs_file_splice_read(
402 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 402 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
403 return -EIO; 403 return -EIO;
404 404
405 xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
406
407 trace_xfs_file_splice_read(ip, count, *ppos, ioflags); 405 trace_xfs_file_splice_read(ip, count, *ppos, ioflags);
408 406
409 /* for dax, we need to avoid the page cache */ 407 /*
410 if (IS_DAX(VFS_I(ip))) 408 * DAX inodes cannot ues the page cache for splice, so we have to push
411 ret = default_file_splice_read(infilp, ppos, pipe, count, flags); 409 * them through the VFS IO path. This means it goes through
412 else 410 * ->read_iter, which for us takes the XFS_IOLOCK_SHARED. Hence we
413 ret = generic_file_splice_read(infilp, ppos, pipe, count, flags); 411 * cannot lock the splice operation at this level for DAX inodes.
414 if (ret > 0) 412 */
415 XFS_STATS_ADD(ip->i_mount, xs_read_bytes, ret); 413 if (IS_DAX(VFS_I(ip))) {
414 ret = default_file_splice_read(infilp, ppos, pipe, count,
415 flags);
416 goto out;
417 }
416 418
419 xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
420 ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
417 xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); 421 xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
422out:
423 if (ret > 0)
424 XFS_STATS_ADD(ip->i_mount, xs_read_bytes, ret);
418 return ret; 425 return ret;
419} 426}
420 427