From: Hugh Dickins Clean up mremap move's copy_one_pte: - get_one_pte_map_nested already weeded out the pte_none case, now don't even call copy_one_pte if it has nothing to do. - check pfn_valid before passing page to page_remove_rmap. --- 25-akpm/mm/mremap.c | 31 ++++++++++++------------------- 1 files changed, 12 insertions(+), 19 deletions(-) diff -puN mm/mremap.c~mremap-copy_one_pte-fix mm/mremap.c --- 25/mm/mremap.c~mremap-copy_one_pte-fix 2004-04-03 03:00:17.864515736 -0800 +++ 25-akpm/mm/mremap.c 2004-04-03 03:00:17.867515280 -0800 @@ -79,31 +79,21 @@ static inline pte_t *alloc_one_pte_map(s return pte; } -static int +static void copy_one_pte(struct vm_area_struct *vma, unsigned long old_addr, pte_t *src, pte_t *dst, struct pte_chain **pte_chainp) { - int error = 0; - pte_t pte; - struct page *page = NULL; - - if (pte_present(*src)) - page = pte_page(*src); + pte_t pte = ptep_clear_flush(vma, old_addr, src); + set_pte(dst, pte); - if (!pte_none(*src)) { - if (page) + if (pte_present(pte)) { + unsigned long pfn = pte_pfn(pte); + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); page_remove_rmap(page, src); - pte = ptep_clear_flush(vma, old_addr, src); - if (!dst) { - /* No dest? We must put it back. */ - dst = src; - error++; - } - set_pte(dst, pte); - if (page) *pte_chainp = page_add_rmap(page, dst, *pte_chainp); + } } - return error; } static int @@ -140,8 +130,11 @@ move_one_page(struct vm_area_struct *vma * page_table_lock, we should re-check the src entry... */ if (src) { - error = copy_one_pte(vma, old_addr, src, + if (dst) + copy_one_pte(vma, old_addr, src, dst, &pte_chain); + else + error = -ENOMEM; pte_unmap_nested(src); } pte_unmap(dst); _