|
@@ -402,19 +402,26 @@ xfs_file_splice_read(
|
|
|
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
|
|
|
return -EIO;
|
|
|
|
|
|
- xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
|
|
|
-
|
|
|
trace_xfs_file_splice_read(ip, count, *ppos, ioflags);
|
|
|
|
|
|
- /* for dax, we need to avoid the page cache */
|
|
|
- if (IS_DAX(VFS_I(ip)))
|
|
|
- ret = default_file_splice_read(infilp, ppos, pipe, count, flags);
|
|
|
- else
|
|
|
- ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
|
|
|
- if (ret > 0)
|
|
|
- XFS_STATS_ADD(ip->i_mount, xs_read_bytes, ret);
|
|
|
+ /*
|
|
|
+ * DAX inodes cannot ues the page cache for splice, so we have to push
|
|
|
+ * them through the VFS IO path. This means it goes through
|
|
|
+ * ->read_iter, which for us takes the XFS_IOLOCK_SHARED. Hence we
|
|
|
+ * cannot lock the splice operation at this level for DAX inodes.
|
|
|
+ */
|
|
|
+ if (IS_DAX(VFS_I(ip))) {
|
|
|
+ ret = default_file_splice_read(infilp, ppos, pipe, count,
|
|
|
+ flags);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
+ xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
|
|
|
+ ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
|
|
|
xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
|
|
|
+out:
|
|
|
+ if (ret > 0)
|
|
|
+ XFS_STATS_ADD(ip->i_mount, xs_read_bytes, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|