diff options
| -rw-r--r-- | mm/mremap.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/mm/mremap.c b/mm/mremap.c index 85b492d23b4b..8d7a636e8b2a 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -135,15 +135,17 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr, dst = alloc_one_pte_map(mm, new_addr); if (src == NULL) src = get_one_pte_map_nested(mm, old_addr); - error = copy_one_pte(vma, old_addr, src, dst, &pte_chain); - pte_unmap_nested(src); - pte_unmap(dst); - } else /* - * Why do we need this flush ? If there is no pte for - * old_addr, then there must not be a pte for it as well. + * Since alloc_one_pte_map can drop and re-acquire + * page_table_lock, we should re-check the src entry... */ - flush_tlb_page(vma, old_addr); + if (src) { + error = copy_one_pte(vma, old_addr, src, + dst, &pte_chain); + pte_unmap_nested(src); + } + pte_unmap(dst); + } spin_unlock(&mm->page_table_lock); pte_chain_free(pte_chain); out: |
