All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mm/filemap: Fix filemap_map_pages for THP
@ 2020-09-11  1:25 Matthew Wilcox (Oracle)
  2020-09-11 14:34 ` Kirill A. Shutemov
  0 siblings, 1 reply; 2+ messages in thread
From: Matthew Wilcox (Oracle) @ 2020-09-11  1:25 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matthew Wilcox (Oracle), linux-mm, Kirill A. Shutemov, William Kucharski

We dereference page->mapping and page->index directly after calling
find_subpage() and these fields are not valid for tail pages.  While
commit 4101196b19d7 introduced the call to find_subpage(), the problem
existed prior to this; I'm going to suggest all the way back to when
THPs first existed.

The user-visible effects of this are almost negligible.  To hit it, you
have to mmap a tmpfs file at an unaligned address and then it's only
a disabled optimisation causing page faults to happen more frequently
than they otherwise would.

Fix this by keeping both head and page pointers and checking the
appropriate one.  We could use page_mapping() and page_to_index(),
but that's higher overhead.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 mm/filemap.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index cb5f49fe8029..c774c8154107 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2786,42 +2786,42 @@ void filemap_map_pages(struct vm_fault *vmf,
 	pgoff_t last_pgoff = start_pgoff;
 	unsigned long max_idx;
 	XA_STATE(xas, &mapping->i_pages, start_pgoff);
-	struct page *page;
+	struct page *head, *page;
 	unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
 
 	rcu_read_lock();
-	xas_for_each(&xas, page, end_pgoff) {
-		if (xas_retry(&xas, page))
+	xas_for_each(&xas, head, end_pgoff) {
+		if (xas_retry(&xas, head))
 			continue;
-		if (xa_is_value(page))
+		if (xa_is_value(head))
 			goto next;
 
 		/*
 		 * Check for a locked page first, as a speculative
 		 * reference may adversely influence page migration.
 		 */
-		if (PageLocked(page))
+		if (PageLocked(head))
 			goto next;
-		if (!page_cache_get_speculative(page))
+		if (!page_cache_get_speculative(head))
 			goto next;
 
 		/* Has the page moved or been split? */
-		if (unlikely(page != xas_reload(&xas)))
+		if (unlikely(head != xas_reload(&xas)))
 			goto skip;
-		page = find_subpage(page, xas.xa_index);
+		page = find_subpage(head, xas.xa_index);
 
-		if (!PageUptodate(page) ||
+		if (!PageUptodate(head) ||
 				PageReadahead(page) ||
 				PageHWPoison(page))
 			goto skip;
-		if (!trylock_page(page))
+		if (!trylock_page(head))
 			goto skip;
 
-		if (page->mapping != mapping || !PageUptodate(page))
+		if (head->mapping != mapping || !PageUptodate(head))
 			goto unlock;
 
 		max_idx = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
-		if (page->index >= max_idx)
+		if (xas.xa_index >= max_idx)
 			goto unlock;
 
 		if (mmap_miss > 0)
@@ -2833,12 +2833,12 @@ void filemap_map_pages(struct vm_fault *vmf,
 		last_pgoff = xas.xa_index;
 		if (alloc_set_pte(vmf, page))
 			goto unlock;
-		unlock_page(page);
+		unlock_page(head);
 		goto next;
 unlock:
-		unlock_page(page);
+		unlock_page(head);
 skip:
-		put_page(page);
+		put_page(head);
 next:
 		/* Huge page is mapped? No need to proceed. */
 		if (pmd_trans_huge(*vmf->pmd))
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] mm/filemap: Fix filemap_map_pages for THP
  2020-09-11  1:25 [PATCH] mm/filemap: Fix filemap_map_pages for THP Matthew Wilcox (Oracle)
@ 2020-09-11 14:34 ` Kirill A. Shutemov
  0 siblings, 0 replies; 2+ messages in thread
From: Kirill A. Shutemov @ 2020-09-11 14:34 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: Andrew Morton, linux-mm, William Kucharski

On Fri, Sep 11, 2020 at 02:25:32AM +0100, Matthew Wilcox (Oracle) wrote:
> We dereference page->mapping and page->index directly after calling
> find_subpage() and these fields are not valid for tail pages.  While
> commit 4101196b19d7 introduced the call to find_subpage(), the problem
> existed prior to this; I'm going to suggest all the way back to when
> THPs first existed.

When hugetmpfs made upstream.

> The user-visible effects of this are almost negligible.  To hit it, you
> have to mmap a tmpfs file at an unaligned address and then it's only
> a disabled optimisation causing page faults to happen more frequently
> than they otherwise would.
> 
> Fix this by keeping both head and page pointers and checking the
> appropriate one.  We could use page_mapping() and page_to_index(),
> but that's higher overhead.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>

-- 
 Kirill A. Shutemov


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-09-11 14:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-11  1:25 [PATCH] mm/filemap: Fix filemap_map_pages for THP Matthew Wilcox (Oracle)
2020-09-11 14:34 ` Kirill A. Shutemov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.