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 <michel@xxxxxxxxxxxxxx> --- 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