]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/xfs/xfs_file.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / fs / xfs / xfs_file.c
index f5392ab2def1ab806aa075bcc19643cbac6ca8f9..ebe9b8290a705c402759c985c015b0bbc5f6a151 100644 (file)
@@ -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;
 }