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>
This commit is contained in:
Родитель
653c60b633
Коммит
de0e8c20ba
|
@ -1379,6 +1379,32 @@ xfs_file_llseek(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Locking for serialisation of IO during page faults. This results in a lock
|
||||
* ordering of:
|
||||
*
|
||||
* mmap_sem (MM)
|
||||
* i_mmap_lock (XFS - truncate serialisation)
|
||||
* page_lock (MM)
|
||||
* i_lock (XFS - extent map serialisation)
|
||||
*/
|
||||
STATIC int
|
||||
xfs_filemap_fault(
|
||||
struct vm_area_struct *vma,
|
||||
struct vm_fault *vmf)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(vma->vm_file->f_mapping->host);
|
||||
int error;
|
||||
|
||||
trace_xfs_filemap_fault(ip);
|
||||
|
||||
xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
|
||||
error = filemap_fault(vma, vmf);
|
||||
xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
const struct file_operations xfs_file_operations = {
|
||||
.llseek = xfs_file_llseek,
|
||||
.read = new_sync_read,
|
||||
|
@ -1411,7 +1437,7 @@ const struct file_operations xfs_dir_file_operations = {
|
|||
};
|
||||
|
||||
static const struct vm_operations_struct xfs_file_vm_ops = {
|
||||
.fault = filemap_fault,
|
||||
.fault = xfs_filemap_fault,
|
||||
.map_pages = filemap_map_pages,
|
||||
.page_mkwrite = xfs_vm_page_mkwrite,
|
||||
};
|
||||
|
|
|
@ -685,6 +685,8 @@ DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag);
|
|||
DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag);
|
||||
DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid);
|
||||
|
||||
DEFINE_INODE_EVENT(xfs_filemap_fault);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_iref_class,
|
||||
TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip),
|
||||
TP_ARGS(ip, caller_ip),
|
||||
|
|
Загрузка…
Ссылка в новой задаче