Commit f8ad0f499fad5cdbcaaa2d97542b2db869b5a770

Authored by Johannes Weiner
Committed by Linus Torvalds
1 parent e9bb35df6f

mm: introduce follow_pte()

A generic readonly page table lookup helper to map an address space and an
address from it to a pte.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Christoph Hellwig <hch@infradead.org>
Acked-by: Magnus Damm <magnus.damm@gmail.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 37 additions and 0 deletions Side-by-side Diff

... ... @@ -3103,6 +3103,43 @@
3103 3103  
3104 3104 #endif /* __HAVE_ARCH_GATE_AREA */
3105 3105  
  3106 +static int follow_pte(struct mm_struct *mm, unsigned long address,
  3107 + pte_t **ptepp, spinlock_t **ptlp)
  3108 +{
  3109 + pgd_t *pgd;
  3110 + pud_t *pud;
  3111 + pmd_t *pmd;
  3112 + pte_t *ptep;
  3113 +
  3114 + pgd = pgd_offset(mm, address);
  3115 + if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
  3116 + goto out;
  3117 +
  3118 + pud = pud_offset(pgd, address);
  3119 + if (pud_none(*pud) || unlikely(pud_bad(*pud)))
  3120 + goto out;
  3121 +
  3122 + pmd = pmd_offset(pud, address);
  3123 + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
  3124 + goto out;
  3125 +
  3126 + /* We cannot handle huge page PFN maps. Luckily they don't exist. */
  3127 + if (pmd_huge(*pmd))
  3128 + goto out;
  3129 +
  3130 + ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
  3131 + if (!ptep)
  3132 + goto out;
  3133 + if (!pte_present(*ptep))
  3134 + goto unlock;
  3135 + *ptepp = ptep;
  3136 + return 0;
  3137 +unlock:
  3138 + pte_unmap_unlock(ptep, *ptlp);
  3139 +out:
  3140 + return -EINVAL;
  3141 +}
  3142 +
3106 3143 #ifdef CONFIG_HAVE_IOREMAP_PROT
3107 3144 int follow_phys(struct vm_area_struct *vma,
3108 3145 unsigned long address, unsigned int flags,