diff options
author | Johannes Weiner <hannes@cmpxchg.org> | 2009-06-16 18:32:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 22:47:40 -0400 |
commit | 03668a4debf4f50de55c34b6e66dae63e1c73716 (patch) | |
tree | d4fedb9feb056b8383b0d75e2cad5bf8ceeb8c8c | |
parent | f8ad0f499fad5cdbcaaa2d97542b2db869b5a770 (diff) |
mm: use generic follow_pte() in follow_phys()
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>
-rw-r--r-- | mm/memory.c | 36 |
1 files changed, 5 insertions, 31 deletions
diff --git a/mm/memory.c b/mm/memory.c index 7135d6b25995..24ff20480bb7 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -3145,50 +3145,24 @@ int follow_phys(struct vm_area_struct *vma, | |||
3145 | unsigned long address, unsigned int flags, | 3145 | unsigned long address, unsigned int flags, |
3146 | unsigned long *prot, resource_size_t *phys) | 3146 | unsigned long *prot, resource_size_t *phys) |
3147 | { | 3147 | { |
3148 | pgd_t *pgd; | 3148 | int ret = -EINVAL; |
3149 | pud_t *pud; | ||
3150 | pmd_t *pmd; | ||
3151 | pte_t *ptep, pte; | 3149 | pte_t *ptep, pte; |
3152 | spinlock_t *ptl; | 3150 | spinlock_t *ptl; |
3153 | resource_size_t phys_addr = 0; | ||
3154 | struct mm_struct *mm = vma->vm_mm; | ||
3155 | int ret = -EINVAL; | ||
3156 | 3151 | ||
3157 | if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) | 3152 | if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) |
3158 | goto out; | 3153 | goto out; |
3159 | 3154 | ||
3160 | pgd = pgd_offset(mm, address); | 3155 | if (follow_pte(vma->vm_mm, address, &ptep, &ptl)) |
3161 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | ||
3162 | goto out; | ||
3163 | |||
3164 | pud = pud_offset(pgd, address); | ||
3165 | if (pud_none(*pud) || unlikely(pud_bad(*pud))) | ||
3166 | goto out; | ||
3167 | |||
3168 | pmd = pmd_offset(pud, address); | ||
3169 | if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | ||
3170 | goto out; | ||
3171 | |||
3172 | /* We cannot handle huge page PFN maps. Luckily they don't exist. */ | ||
3173 | if (pmd_huge(*pmd)) | ||
3174 | goto out; | 3156 | goto out; |
3175 | |||
3176 | ptep = pte_offset_map_lock(mm, pmd, address, &ptl); | ||
3177 | if (!ptep) | ||
3178 | goto out; | ||
3179 | |||
3180 | pte = *ptep; | 3157 | pte = *ptep; |
3181 | if (!pte_present(pte)) | 3158 | |
3182 | goto unlock; | ||
3183 | if ((flags & FOLL_WRITE) && !pte_write(pte)) | 3159 | if ((flags & FOLL_WRITE) && !pte_write(pte)) |
3184 | goto unlock; | 3160 | goto unlock; |
3185 | phys_addr = pte_pfn(pte); | ||
3186 | phys_addr <<= PAGE_SHIFT; /* Shift here to avoid overflow on PAE */ | ||
3187 | 3161 | ||
3188 | *prot = pgprot_val(pte_pgprot(pte)); | 3162 | *prot = pgprot_val(pte_pgprot(pte)); |
3189 | *phys = phys_addr; | 3163 | *phys = (resource_size_t)pte_pfn(pte) << PAGE_SHIFT; |
3190 | ret = 0; | ||
3191 | 3164 | ||
3165 | ret = 0; | ||
3192 | unlock: | 3166 | unlock: |
3193 | pte_unmap_unlock(ptep, ptl); | 3167 | pte_unmap_unlock(ptep, ptl); |
3194 | out: | 3168 | out: |