linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Toshi Kani <toshi.kani@hpe.com>
To: akpm@linux-foundation.org
Cc: kirill.shutemov@linux.intel.com, willy@linux.intel.com,
	ross.zwisler@linux.intel.com, dan.j.williams@intel.com,
	mauricio.porto@hpe.com, linux-mm@kvack.org,
	linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org,
	linux-kernel@vger.kernel.org, Toshi Kani <toshi.kani@hpe.com>
Subject: [PATCH] mm: Fix mmap MAP_POPULATE for DAX pmd mapping
Date: Mon, 23 Nov 2015 13:04:42 -0700	[thread overview]
Message-ID: <1448309082-20851-1-git-send-email-toshi.kani@hpe.com> (raw)

The following oops was observed when mmap() with MAP_POPULATE
pre-faulted pmd mappings of a DAX file.  follow_trans_huge_pmd()
expects that a target address has a struct page.

  BUG: unable to handle kernel paging request at ffffea0012220000
  follow_trans_huge_pmd+0xba/0x390
  follow_page_mask+0x33d/0x420
  __get_user_pages+0xdc/0x800
  populate_vma_page_range+0xb5/0xe0
  __mm_populate+0xc5/0x150
  vm_mmap_pgoff+0xd5/0xe0
  SyS_mmap_pgoff+0x1c1/0x290
  SyS_mmap+0x1b/0x30

Fix it by making the PMD pre-fault handling consistent with PTE.
After pre-faulted in faultin_page(), follow_page_mask() calls
follow_trans_huge_pmd(), which is changed to call follow_pfn_pmd()
for VM_PFNMAP or VM_MIXEDMAP.  follow_pfn_pmd() handles FOLL_TOUCH
and returns with -EEXIST.

Reported-by: Mauricio Porto <mauricio.porto@hpe.com>
Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
---
 mm/huge_memory.c |   34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d5b8920..f56e034 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1267,6 +1267,32 @@ out_unlock:
 	return ret;
 }
 
+/*
+ * Follow a pmd inserted by vmf_insert_pfn_pmd(). See follow_pfn_pte() for pte.
+ */
+static int follow_pfn_pmd(struct vm_area_struct *vma, unsigned long address,
+		pmd_t *pmd, unsigned int flags)
+{
+	/* No page to get reference */
+	if (flags & FOLL_GET)
+		return -EFAULT;
+
+	if (flags & FOLL_TOUCH) {
+		pmd_t entry = *pmd;
+
+		/* Set the dirty bit per follow_trans_huge_pmd() */
+		entry = pmd_mkyoung(pmd_mkdirty(entry));
+
+		if (!pmd_same(*pmd, entry)) {
+			set_pmd_at(vma->vm_mm, address, pmd, entry);
+			update_mmu_cache_pmd(vma, address, pmd);
+		}
+	}
+
+	/* Proper page table entry exists, but no corresponding struct page */
+	return -EEXIST;
+}
+
 struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 				   unsigned long addr,
 				   pmd_t *pmd,
@@ -1274,6 +1300,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct page *page = NULL;
+	int ret;
 
 	assert_spin_locked(pmd_lockptr(mm, pmd));
 
@@ -1288,6 +1315,13 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 	if ((flags & FOLL_NUMA) && pmd_protnone(*pmd))
 		goto out;
 
+	/* pfn map does not have a struct page */
+	if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) {
+		ret = follow_pfn_pmd(vma, addr, pmd, flags);
+		page = ERR_PTR(ret);
+		goto out;
+	}
+
 	page = pmd_page(*pmd);
 	VM_BUG_ON_PAGE(!PageHead(page), page);
 	if (flags & FOLL_TOUCH) {

             reply	other threads:[~2015-11-23 20:09 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-23 20:04 Toshi Kani [this message]
2015-11-23 20:53 ` [PATCH] mm: Fix mmap MAP_POPULATE for DAX pmd mapping Dan Williams
2015-11-23 22:15   ` Toshi Kani
2015-11-30 22:08 ` Dan Williams
2015-12-02  2:19   ` Toshi Kani
2015-12-02  3:45     ` Dan Williams
2015-12-02 17:43       ` Toshi Kani
2015-12-02 17:01         ` Dan Williams
2015-12-02 18:06           ` Dan Williams
2015-12-02 19:26             ` Toshi Kani
2015-12-02 19:00               ` Dan Williams
2015-12-02 20:02                 ` Toshi Kani
2015-12-02 20:12                   ` Toshi Kani
2015-12-02 19:57                     ` Dan Williams
2015-12-02 21:37                       ` Toshi Kani
2015-12-02 20:54                         ` Dan Williams
2015-12-02 21:55                           ` Toshi Kani
2015-12-03 23:43                             ` Dan Williams
2015-12-04 16:55                               ` Toshi Kani
2015-12-02 22:00                           ` Dave Hansen
2015-12-02 22:03                             ` Dan Williams
2015-12-02 22:09                               ` Dave Hansen
2015-12-03  0:21         ` Toshi Kani
2015-12-02 23:33           ` Dan Williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1448309082-20851-1-git-send-email-toshi.kani@hpe.com \
    --to=toshi.kani@hpe.com \
    --cc=akpm@linux-foundation.org \
    --cc=dan.j.williams@intel.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-nvdimm@ml01.01.org \
    --cc=mauricio.porto@hpe.com \
    --cc=ross.zwisler@linux.intel.com \
    --cc=willy@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).