The patch titled Subject: filemap-drop-the-mmap_sem-for-all-blocking-operations-v6 has been removed from the -mm tree. Its filename was filemap-drop-the-mmap_sem-for-all-blocking-operations-v6.patch This patch was dropped because it was folded into filemap-drop-the-mmap_sem-for-all-blocking-operations.patch ------------------------------------------------------ From: Josef Bacik <josef@xxxxxxxxxxxxxx> Subject: filemap-drop-the-mmap_sem-for-all-blocking-operations-v6 - added more comments as per Andrew's suggestion. - fixed the fpin leaks in the two error paths that were pointed out. Link: http://lkml.kernel.org/r/20181212152757.10017-1-josef@xxxxxxxxxxxxxx Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx> Acked-by: Johannes Weiner <hannes@xxxxxxxxxxx> Reviewed-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Dave Chinner <david@xxxxxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: Rik van Riel <riel@xxxxxxxxxx> Cc: Tejun Heo <tj@xxxxxxxxxx> Cc: "Kirill A. Shutemov" <kirill@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/filemap.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) --- a/mm/filemap.c~filemap-drop-the-mmap_sem-for-all-blocking-operations-v6 +++ a/mm/filemap.c @@ -2396,6 +2396,12 @@ static struct file *maybe_unlock_mmap_fo int flags = vmf->flags; if (fpin) return fpin; + + /* + * FAULT_FLAG_RETRY_NOWAIT means we don't want to wait on page locks or + * anything, so we only pin the file and drop the mmap_sem if only + * FAULT_FLAG_ALLOW_RETRY is set. + */ if ((flags & (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT)) == FAULT_FLAG_ALLOW_RETRY) { fpin = get_file(vmf->vma->vm_file); @@ -2405,10 +2411,15 @@ static struct file *maybe_unlock_mmap_fo } /* - * Works similar to lock_page_or_retry, except it will pin the file and drop the - * mmap_sem if necessary and then lock the page, and return 1 in this case. - * This means the caller needs to deal with the fpin appropriately. 0 return is - * the same as in lock_page_or_retry. + * lock_page_maybe_drop_mmap - lock the page, possibly dropping the mmap_sem + * @vmf - the vm_fault for this fault. + * @page - the page to lock. + * @fpin - the pointer to the file we may pin (or is already pinned). + * + * This works similar to lock_page_or_retry in that it can drop the mmap_sem. + * It differs in that it actually returns the page locked if it returns 1 and 0 + * if it couldn't lock the page. If we did have to drop the mmap_sem then fpin + * will point to the pinned file and needs to be fput()'ed at a later point. */ static int lock_page_maybe_drop_mmap(struct vm_fault *vmf, struct page *page, struct file **fpin) @@ -2416,9 +2427,10 @@ static int lock_page_maybe_drop_mmap(str if (trylock_page(page)) return 1; - *fpin = maybe_unlock_mmap_for_io(vmf, *fpin); if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) return 0; + + *fpin = maybe_unlock_mmap_for_io(vmf, *fpin); if (vmf->flags & FAULT_FLAG_KILLABLE) { if (__lock_page_killable(page)) { /* @@ -2438,8 +2450,11 @@ static int lock_page_maybe_drop_mmap(str /* - * Synchronous readahead happens when we don't even find - * a page in the page cache at all. + * Synchronous readahead happens when we don't even find a page in the page + * cache at all. We don't want to perform IO under the mmap sem, so if we have + * to drop the mmap sem we return the file that was pinned in order for us to do + * that. If we didn't pin a file then we return NULL. The file that is + * returned needs to be fput()'ed when we're done with it. */ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) { @@ -2486,7 +2501,8 @@ static struct file *do_sync_mmap_readahe /* * Asynchronous readahead happens when we find the page and PG_readahead, - * so we want to possibly extend the readahead further.. + * so we want to possibly extend the readahead further. We return the file that + * was pinned if we have to drop the mmap_sem in order to do IO. */ static struct file *do_async_mmap_readahead(struct vm_fault *vmf, struct page *page) @@ -2572,14 +2588,15 @@ retry_find: page = pagecache_get_page(mapping, offset, FGP_CREAT|FGP_FOR_MMAP, vmf->gfp_mask); - if (!page) + if (!page) { + if (fpin) + goto out_retry; return vmf_error(-ENOMEM); + } } - if (!lock_page_maybe_drop_mmap(vmf, page, &fpin)) { - put_page(page); - return ret | VM_FAULT_RETRY; - } + if (!lock_page_maybe_drop_mmap(vmf, page, &fpin)) + goto out_retry; /* Did it get truncated? */ if (unlikely(page->mapping != mapping)) { _ Patches currently in -mm which might be from josef@xxxxxxxxxxxxxx are filemap-kill-page_cache_read-usage-in-filemap_fault.patch filemap-pass-vm_fault-to-the-mmap-ra-helpers.patch filemap-drop-the-mmap_sem-for-all-blocking-operations.patch