We just need to make sure ext4_filemap_fault() doesn't block in the
speculative case as it is called with an rcu read lock held.

Signed-off-by: Michel Lespinasse <mic...@lespinasse.org>
---
 fs/ext4/file.c  | 1 +
 fs/ext4/inode.c | 7 ++++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 194f5d00fa32..546b9d4aa9d7 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -742,6 +742,7 @@ static const struct vm_operations_struct ext4_file_vm_ops = 
{
        .fault          = ext4_filemap_fault,
        .map_pages      = filemap_map_pages,
        .page_mkwrite   = ext4_page_mkwrite,
+       .speculative    = true,
 };
 
 static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0948a43f1b3d..370484403c71 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6192,7 +6192,12 @@ vm_fault_t ext4_filemap_fault(struct vm_fault *vmf)
        struct inode *inode = file_inode(vmf->vma->vm_file);
        vm_fault_t ret;
 
-       down_read(&EXT4_I(inode)->i_mmap_sem);
+       if (vmf->flags & FAULT_FLAG_SPECULATIVE) {
+               if (!down_read_trylock(&EXT4_I(inode)->i_mmap_sem))
+                       return VM_FAULT_RETRY;
+       } else {
+               down_read(&EXT4_I(inode)->i_mmap_sem);
+       }
        ret = filemap_fault(vmf);
        up_read(&EXT4_I(inode)->i_mmap_sem);
 
-- 
2.20.1

Reply via email to