@@ -3772,8 +3772,8 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
3772
3772
}
3773
3773
#endif /* __PAGETABLE_PMD_FOLDED */
3774
3774
3775
- static int __follow_pte (struct mm_struct * mm , unsigned long address ,
3776
- pte_t * * ptepp , spinlock_t * * ptlp )
3775
+ static int __follow_pte_pmd (struct mm_struct * mm , unsigned long address ,
3776
+ pte_t * * ptepp , pmd_t * * pmdpp , spinlock_t * * ptlp )
3777
3777
{
3778
3778
pgd_t * pgd ;
3779
3779
pud_t * pud ;
@@ -3790,11 +3790,20 @@ static int __follow_pte(struct mm_struct *mm, unsigned long address,
3790
3790
3791
3791
pmd = pmd_offset (pud , address );
3792
3792
VM_BUG_ON (pmd_trans_huge (* pmd ));
3793
- if (pmd_none (* pmd ) || unlikely (pmd_bad (* pmd )))
3794
- goto out ;
3795
3793
3796
- /* We cannot handle huge page PFN maps. Luckily they don't exist. */
3797
- if (pmd_huge (* pmd ))
3794
+ if (pmd_huge (* pmd )) {
3795
+ if (!pmdpp )
3796
+ goto out ;
3797
+
3798
+ * ptlp = pmd_lock (mm , pmd );
3799
+ if (pmd_huge (* pmd )) {
3800
+ * pmdpp = pmd ;
3801
+ return 0 ;
3802
+ }
3803
+ spin_unlock (* ptlp );
3804
+ }
3805
+
3806
+ if (pmd_none (* pmd ) || unlikely (pmd_bad (* pmd )))
3798
3807
goto out ;
3799
3808
3800
3809
ptep = pte_offset_map_lock (mm , pmd , address , ptlp );
@@ -3817,9 +3826,23 @@ int follow_pte(struct mm_struct *mm, unsigned long address, pte_t **ptepp,
3817
3826
3818
3827
/* (void) is needed to make gcc happy */
3819
3828
(void ) __cond_lock (* ptlp ,
3820
- !(res = __follow_pte (mm , address , ptepp , ptlp )));
3829
+ !(res = __follow_pte_pmd (mm , address , ptepp , NULL ,
3830
+ ptlp )));
3831
+ return res ;
3832
+ }
3833
+
3834
+ int follow_pte_pmd (struct mm_struct * mm , unsigned long address ,
3835
+ pte_t * * ptepp , pmd_t * * pmdpp , spinlock_t * * ptlp )
3836
+ {
3837
+ int res ;
3838
+
3839
+ /* (void) is needed to make gcc happy */
3840
+ (void ) __cond_lock (* ptlp ,
3841
+ !(res = __follow_pte_pmd (mm , address , ptepp , pmdpp ,
3842
+ ptlp )));
3821
3843
return res ;
3822
3844
}
3845
+ EXPORT_SYMBOL (follow_pte_pmd );
3823
3846
3824
3847
/**
3825
3848
* follow_pfn - look up PFN at a user virtual address
0 commit comments