From: Yulei Zhang <yuleixzh...@tencent.com>

follow_pfn() will get pfn of pmd if huge pmd is encountered.

Signed-off-by: Chen Zhuo <sagazc...@tencent.com>
Signed-off-by: Yulei Zhang <yuleixzh...@tencent.com>
---
 mm/memory.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/mm/memory.c b/mm/memory.c
index 2d2c0f8a966b..ca42a6e56e9b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4644,15 +4644,23 @@ int follow_pfn(struct vm_area_struct *vma, unsigned 
long address,
        int ret = -EINVAL;
        spinlock_t *ptl;
        pte_t *ptep;
+       pmd_t *pmdp = NULL;
 
        if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
                return ret;
 
-       ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
+       ret = follow_pte_pmd(vma->vm_mm, address, NULL, &ptep, &pmdp, &ptl);
        if (ret)
                return ret;
-       *pfn = pte_pfn(*ptep);
-       pte_unmap_unlock(ptep, ptl);
+
+       if (pmdp) {
+               *pfn = pmd_pfn(*pmdp) + ((address & ~PMD_MASK) >> PAGE_SHIFT);
+               spin_unlock(ptl);
+       } else {
+               *pfn = pte_pfn(*ptep);
+               pte_unmap_unlock(ptep, ptl);
+       }
+
        return 0;
 }
 EXPORT_SYMBOL(follow_pfn);
-- 
2.28.0

Reply via email to