Skip to content

Commit 349d167

Browse files
xzpeterakpm00
authored andcommitted
mm/hugetlb: fix pgtable lock on pmd sharing
Huge pmd sharing operates on PUD not PMD, huge_pte_lock() is not suitable in this case because it should only work for last level pte changes, while pmd sharing is always one level higher. Meanwhile, here we're locking over the spte pgtable lock which is even not a lock for current mm but someone else's. It seems even racy on operating on the lock, as after put_page() of the spte pgtable page logically the page can be released, so at least the spin_unlock() needs to be done after the put_page(). No report I am aware, I'm not even sure whether it'll just work on taking the spte pmd lock, because while we're holding i_mmap read lock it probably means the vma interval tree is frozen, all pte allocators over this pud entry could always find the specific svma and spte page, so maybe they'll serialize on this spte page lock? Even so, doesn't seem to be expected. It just seems to be an accident of cb900f4. Fix it with the proper pud lock (which is the mm's page_table_lock). Link: https://lkml.kernel.org/r/[email protected] Fixes: cb900f4 ("mm, hugetlb: convert hugetlbfs to use split pmd lock") Signed-off-by: Peter Xu <[email protected]> Reviewed-by: Mike Kravetz <[email protected]> Cc: Naoya Horiguchi <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent b95826c commit 349d167

File tree

1 file changed

+2
-3
lines changed

1 file changed

+2
-3
lines changed

mm/hugetlb.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7130,7 +7130,6 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma,
71307130
unsigned long saddr;
71317131
pte_t *spte = NULL;
71327132
pte_t *pte;
7133-
spinlock_t *ptl;
71347133

71357134
i_mmap_lock_read(mapping);
71367135
vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
@@ -7151,15 +7150,15 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma,
71517150
if (!spte)
71527151
goto out;
71537152

7154-
ptl = huge_pte_lock(hstate_vma(vma), mm, spte);
7153+
spin_lock(&mm->page_table_lock);
71557154
if (pud_none(*pud)) {
71567155
pud_populate(mm, pud,
71577156
(pmd_t *)((unsigned long)spte & PAGE_MASK));
71587157
mm_inc_nr_pmds(mm);
71597158
} else {
71607159
put_page(virt_to_page(spte));
71617160
}
7162-
spin_unlock(ptl);
7161+
spin_unlock(&mm->page_table_lock);
71637162
out:
71647163
pte = (pte_t *)pmd_alloc(mm, pud, addr);
71657164
i_mmap_unlock_read(mapping);

0 commit comments

Comments
 (0)