aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_file.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-08-25 03:17:01 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:14:59 -0400
commit0c38a2512df272b14ef4238b476a2e4f70da1479 (patch)
treea88374d18dc0d28521d74bbf9ccde245ccaccdda /fs/xfs/xfs_file.c
parent976d167615b64e14bc1491ca51d424e2ba9a5e84 (diff)
xfs: don't serialise direct IO reads on page cache checks
There is no need to grab the i_mutex of the IO lock in exclusive mode if we don't need to invalidate the page cache. Taking these locks on every direct IO effective serialises them as taking the IO lock in exclusive mode has to wait for all shared holders to drop the lock. That only happens when IO is complete, so effective it prevents dispatch of concurrent direct IO reads to the same inode. Fix this by taking the IO lock shared to check the page cache state, and only then drop it and take the IO lock exclusively if there is work to be done. Hence for the normal direct IO case, no exclusive locking will occur. Signed-off-by: Dave Chinner <dchinner@redhat.com> Tested-by: Joern Engel <joern@logfs.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r--fs/xfs/xfs_file.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 7f7b42469ea7..8fd4a0708d30 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -317,7 +317,19 @@ xfs_file_aio_read(
317 if (XFS_FORCED_SHUTDOWN(mp)) 317 if (XFS_FORCED_SHUTDOWN(mp))
318 return -EIO; 318 return -EIO;
319 319
320 if (unlikely(ioflags & IO_ISDIRECT)) { 320 /*
321 * Locking is a bit tricky here. If we take an exclusive lock
322 * for direct IO, we effectively serialise all new concurrent
323 * read IO to this file and block it behind IO that is currently in
324 * progress because IO in progress holds the IO lock shared. We only
325 * need to hold the lock exclusive to blow away the page cache, so
326 * only take lock exclusively if the page cache needs invalidation.
327 * This allows the normal direct IO case of no page cache pages to
328 * proceeed concurrently without serialisation.
329 */
330 xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
331 if ((ioflags & IO_ISDIRECT) && inode->i_mapping->nrpages) {
332 xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
321 xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); 333 xfs_rw_ilock(ip, XFS_IOLOCK_EXCL);
322 334
323 if (inode->i_mapping->nrpages) { 335 if (inode->i_mapping->nrpages) {
@@ -330,8 +342,7 @@ xfs_file_aio_read(
330 } 342 }
331 } 343 }
332 xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); 344 xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
333 } else 345 }
334 xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
335 346
336 trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags); 347 trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags);
337 348