Messages in this thread Patch in this message | | | Date | Sun, 12 Oct 2003 12:51:46 -0700 | From | William Lee Irwin III <> | Subject | Re: [RFC] invalidate_mmap_range() misses remap_file_pages()-affected targets |
| |
William Lee Irwin III <wli@holomorphy.com> wrote: >> It would seem that mincore() shares a similar issue on account of its >> algorithm
On Sun, Oct 12, 2003 at 04:56:44AM -0700, Andrew Morton wrote: > Yes, I think it makes sense to fix mincore(). I don't fully understand the > reasoning behind the three cases though:
Probably because the second case is broken.
William Lee Irwin III <wli@holomorphy.com> wrote: > + if (pte_file(*pte)) > + present = mincore_linear_page(vma, pte_to_pgoff(*pte)); > + else if (!(vma->vm_flags | (VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE))) > + present = pte_present(*pte); > + else > + present = mincore_linear_page(vma, pgoff);
On Sun, Oct 12, 2003 at 04:56:44AM -0700, Andrew Morton wrote: > Could you explain the logic behind each of these? Perhaps with permanent > comments?
I think the PROT_NONE handling is bogus; since we have the pte, we can just override the pgoff-based lookup if the pte is present and ignore vm_flags, and the behavior isn't unique to PROT_NONE anyway. The prior post flubs the case of pte_present(*pte) with unaligned pgoff and rw or ro vma protection.
Mike Galbraith also spotted a typical locking booboo in mincore_page(), fixed here.
-- wli
diff -prauN rfp-2.6.0-test7-bk3-1/mm/mincore.c rfp-2.6.0-test7-bk3-2/mm/mincore.c --- rfp-2.6.0-test7-bk3-1/mm/mincore.c 2003-10-08 12:24:51.000000000 -0700 +++ rfp-2.6.0-test7-bk3-2/mm/mincore.c 2003-10-12 12:36:52.000000000 -0700 @@ -22,7 +22,7 @@ * and is up to date; i.e. that no page-in operation would be required * at this time if an application were to map and access this page. */ -static unsigned char mincore_page(struct vm_area_struct * vma, +static unsigned char mincore_linear_page(struct vm_area_struct *vma, unsigned long pgoff) { unsigned char present = 0; @@ -38,6 +38,67 @@ static unsigned char mincore_page(struct return present; } +static unsigned char mincore_nonlinear_page(struct vm_area_struct *vma, + unsigned long pgoff) +{ + unsigned char present = 0; + unsigned long vaddr; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + spin_lock(&vma->vm_mm->page_table_lock); + vaddr = PAGE_SIZE*(pgoff - vma->vm_pgoff) + vma->vm_start; + pgd = pgd_offset(vma->vm_mm, vaddr); + if (pgd_none(*pgd)) + goto out; + else if (pgd_bad(*pgd)) { + pgd_ERROR(*pgd); + pgd_clear(pgd); + goto out; + } + pmd = pmd_offset(pgd, vaddr); + if (pmd_none(*pmd)) + goto out; + else if (pmd_ERROR(*pmd)) { + pmd_ERROR(*pmd); + pmd_clear(pmd); + goto out; + } + + pte = pte_offset_map(pmd, vaddr); + + /* PTE_FILE ptes have the same file, but pgoff can differ */ + if (pte_file(*pte)) + present = mincore_linear_page(vma, pte_to_pgoff(*pte)); + + /* pte presence overrides the calculated offset */ + else if (pte_present(*pte)) + present = 1; + + /* matching offsets are the faulted in if the pte isn't set */ + else + present = mincore_linear_page(vma, pgoff); + pte_unmap(pte); +out: + spin_unlock(&vma->vm_mm->page_table_lock); + return present; +} + +static inline unsigned char mincore_page(struct vm_area_struct *vma, + unsigned long pgoff) +{ + unsigned char ret; + struct address_space *as = vma->vm_file->f_dentry->d_inode->i_mapping; + down(&as->i_shared_sem); + if (vma->vm_flags & VM_NONLINEAR) + ret = mincore_nonlinear_page(vma, pgoff); + else + ret = mincore_linear_page(vma, pgoff); + up(&as->i_shared_sem); + return ret; +} + static long mincore_vma(struct vm_area_struct * vma, unsigned long start, unsigned long end, unsigned char __user * vec) { - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |