]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xfs: use i_mmaplock on read faults
authorDave Chinner <dchinner@redhat.com>
Mon, 23 Feb 2015 10:44:19 +0000 (21:44 +1100)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 15 Jun 2016 20:29:33 +0000 (21:29 +0100)
commit de0e8c20ba3a65b0f15040aabbefdc1999876e6b upstream.

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>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Cc: Jan Kara <jack@suse.cz>
Cc: xfs@oss.sgi.com
fs/xfs/xfs_file.c
fs/xfs/xfs_trace.h

index c768860e22aba64898e5d8dab77c405eb0141cf8..878ca2a03dd8a282296e15753b08db740d3b5476 100644 (file)
@@ -1417,6 +1417,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,
@@ -1449,7 +1475,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,
        .remap_pages    = generic_file_remap_pages,
index 152f82782630222321bcd234b20c0ffb0a626e34..389e1f16c220752e3b373c80e09b246cdce41fdc 100644 (file)
@@ -684,6 +684,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),