aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-02-23 05:44:19 -0500
committerDave Chinner <david@fromorbit.com>2015-02-23 05:44:19 -0500
commitde0e8c20ba3a65b0f15040aabbefdc1999876e6b (patch)
tree1b727063b3d8c6a41e2ccb6a16f5f8134c566f09 /fs/xfs
parent653c60b633a9019a54a80d64b5ed33ecb214823c (diff)
xfs: use i_mmaplock on read faults
Take the i_mmaplock over read page faults. These come through the ->fault callout, so we need to wrap the generic implementation with the i_mmaplock. While there, add tracepoints for the read fault as it passes through XFS. This gives us a lock order of mmap_sem -> i_mmaplock -> page_lock -> i_lock. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_file.c28
-rw-r--r--fs/xfs/xfs_trace.h2
2 files changed, 29 insertions, 1 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index ce615d12fb44..ac174226244a 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1379,6 +1379,32 @@ xfs_file_llseek(
1379 } 1379 }
1380} 1380}
1381 1381
1382/*
1383 * Locking for serialisation of IO during page faults. This results in a lock
1384 * ordering of:
1385 *
1386 * mmap_sem (MM)
1387 * i_mmap_lock (XFS - truncate serialisation)
1388 * page_lock (MM)
1389 * i_lock (XFS - extent map serialisation)
1390 */
1391STATIC int
1392xfs_filemap_fault(
1393 struct vm_area_struct *vma,
1394 struct vm_fault *vmf)
1395{
1396 struct xfs_inode *ip = XFS_I(vma->vm_file->f_mapping->host);
1397 int error;
1398
1399 trace_xfs_filemap_fault(ip);
1400
1401 xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
1402 error = filemap_fault(vma, vmf);
1403 xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
1404
1405 return error;
1406}
1407
1382const struct file_operations xfs_file_operations = { 1408const struct file_operations xfs_file_operations = {
1383 .llseek = xfs_file_llseek, 1409 .llseek = xfs_file_llseek,
1384 .read = new_sync_read, 1410 .read = new_sync_read,
@@ -1411,7 +1437,7 @@ const struct file_operations xfs_dir_file_operations = {
1411}; 1437};
1412 1438
1413static const struct vm_operations_struct xfs_file_vm_ops = { 1439static const struct vm_operations_struct xfs_file_vm_ops = {
1414 .fault = filemap_fault, 1440 .fault = xfs_filemap_fault,
1415 .map_pages = filemap_map_pages, 1441 .map_pages = filemap_map_pages,
1416 .page_mkwrite = xfs_vm_page_mkwrite, 1442 .page_mkwrite = xfs_vm_page_mkwrite,
1417}; 1443};
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 51372e34d988..c496153b976b 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -685,6 +685,8 @@ DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag);
685DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag); 685DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag);
686DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); 686DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid);
687 687
688DEFINE_INODE_EVENT(xfs_filemap_fault);
689
688DECLARE_EVENT_CLASS(xfs_iref_class, 690DECLARE_EVENT_CLASS(xfs_iref_class,
689 TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), 691 TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip),
690 TP_ARGS(ip, caller_ip), 692 TP_ARGS(ip, caller_ip),