diff options
author | Dave Chinner <dchinner@redhat.com> | 2015-02-23 05:44:19 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-02-23 05:44:19 -0500 |
commit | de0e8c20ba3a65b0f15040aabbefdc1999876e6b (patch) | |
tree | 1b727063b3d8c6a41e2ccb6a16f5f8134c566f09 /fs/xfs | |
parent | 653c60b633a9019a54a80d64b5ed33ecb214823c (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.c | 28 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 2 |
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 | */ | ||
1391 | STATIC int | ||
1392 | xfs_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 | |||
1382 | const struct file_operations xfs_file_operations = { | 1408 | const 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 | ||
1413 | static const struct vm_operations_struct xfs_file_vm_ops = { | 1439 | static 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); | |||
685 | DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag); | 685 | DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag); |
686 | DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); | 686 | DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); |
687 | 687 | ||
688 | DEFINE_INODE_EVENT(xfs_filemap_fault); | ||
689 | |||
688 | DECLARE_EVENT_CLASS(xfs_iref_class, | 690 | DECLARE_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), |