This is wrong because both routines can be called from within do_file_page, which is called when !pte_present(pte) && !pte_none(pte) && pte_file(pte). I.e. the pte is not zeroed, so it has been used, but the page has been swapped out, or . Actually, in that situation ->populate is called with nonblock == 0, so only install_page can be called there. If ->populate fails, the faulting process will get a SIGBUS; and this *could* happen. The other caller is sys_remap_file_page. In that situation, we fail if !(vma->vm_flags & VM_SHARED), so we don't call ->populate. Actually, however, we could be called inside mmap for MAP_POPULATE. However, even in that case, old mappings have already been unmapped away. And actually, in Ingo's patch things were different, because if remap_file_pages was called only to change protections, without creating non-linear mappings, we didn't punt even if the VM was not shared. So, currently MAP_POPULATE will fail (though without returning any error) if the VMA is private and not shared, without a real reason to do so. But again, after mmap'ing an area, even with MAP_POPULATE, old mappings should have been cleared, so what are we bothering about here? diff -puN mm/fremap.c~remap-file-pages-prot-2.6.13-rc3-A2 mm/fremap.c --- linux-2.6.git/mm/fremap.c~remap-file-pages-prot-2.6.13-rc3-A2 2005-08-03 12:41:36.000000000 +0200 +++ linux-2.6.git-paolo/mm/fremap.c 2005-08-03 12:41:36.000000000 +0200 @@ -90,6 +90,14 @@ int install_page(struct mm_struct *mm, s if (!page->mapping || page->index >= size) goto err_unlock; + /* + * Only install a new page for a non-shared mapping if it's + * not existent yet: + */ + err = -EEXIST; + if (!pte_none(*pte) && !(vma->vm_flags & VM_SHARED)) + goto err_unlock; + zap_pte(mm, vma, addr, pte); inc_mm_counter(mm,rss); @@ -136,6 +146,13 @@ int install_file_pte(struct mm_struct *m err = 0; if (linear && pte_none(*pte)) goto err_unlock; + /* + * Only install a new page for a non-shared mapping if it's + * not existent yet: + */ + err = -EEXIST; + if (!pte_none(*pte) && !(vma->vm_flags & VM_SHARED)) + goto err_unlock; zap_pte(mm, vma, addr, pte); # vim: tw=80