thp: keep highpte mapped until it is no longer needed

Two users reported THP-related crashes on 32-bit x86 machines.  Their oops
reports indicated an invalid pte, and subsequent code inspection showed
that the highpte is actually used after unmap.

The fix is to unmap the pte only after all operations against it are
finished.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Reported-by: Ilya Dryomov <idryomov@gmail.com>
Reported-by: werner <w.landgraf@ru.ru>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Tested-by: Ilya Dryomov <idryomov@gmail.com>
Tested-by: Steven Rostedt <rostedt@goodmis.org
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Johannes Weiner 2011-01-20 14:44:18 -08:00 committed by Linus Torvalds
parent 6a108a14fa
commit 453c719261
1 changed files with 2 additions and 1 deletions

View File

@ -1837,9 +1837,9 @@ static void collapse_huge_page(struct mm_struct *mm,
spin_lock(ptl); spin_lock(ptl);
isolated = __collapse_huge_page_isolate(vma, address, pte); isolated = __collapse_huge_page_isolate(vma, address, pte);
spin_unlock(ptl); spin_unlock(ptl);
pte_unmap(pte);
if (unlikely(!isolated)) { if (unlikely(!isolated)) {
pte_unmap(pte);
spin_lock(&mm->page_table_lock); spin_lock(&mm->page_table_lock);
BUG_ON(!pmd_none(*pmd)); BUG_ON(!pmd_none(*pmd));
set_pmd_at(mm, address, pmd, _pmd); set_pmd_at(mm, address, pmd, _pmd);
@ -1856,6 +1856,7 @@ static void collapse_huge_page(struct mm_struct *mm,
anon_vma_unlock(vma->anon_vma); anon_vma_unlock(vma->anon_vma);
__collapse_huge_page_copy(pte, new_page, vma, address, ptl); __collapse_huge_page_copy(pte, new_page, vma, address, ptl);
pte_unmap(pte);
__SetPageUptodate(new_page); __SetPageUptodate(new_page);
pgtable = pmd_pgtable(_pmd); pgtable = pmd_pgtable(_pmd);
VM_BUG_ON(page_count(pgtable) != 1); VM_BUG_ON(page_count(pgtable) != 1);