Skip to content

Commit 94a3c29

Browse files
pizhenweiBrian Maly
authored andcommitted
mm/rmap: Fix handling of hugetlbfs pages in page_vma_mapped_walk
page_mapped_in_vma() sets nr_pages to 1, which is usually correct as we only want to know about the precise page and not about other pages in the folio. However, hugetlbfs does want to know about the entire hpage, and using nr_pages to get the size of the hpage is wrong. We could change page_mapped_in_vma() to special-case hugetlbfs pages, but it's better to ignore nr_pages in page_vma_mapped_walk() and get the size from the VMA instead. Fixes: 2aff7a4 ("mm: Convert page_vma_mapped_walk to work on PFNs") Signed-off-by: zhenwei pi <[email protected]> Reviewed-by: Muchun Song <[email protected]> Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> [edit commit message, use hstate directly] (cherry picked from commit 98ea025) Conflicts: mm/page_vma_mapped.c Trivial conflicts due to lack of upstream commit 2aff7a4 ("mm: Convert page_vma_mapped_walk to work on PFNs"), and lack of page to folio conversion. This patch fixed a potential kernel Oops issue in upstream that has been caught in UEK7U3 test when injecting MADV_HWPOISON to an anonymous hugetlb tail page. The kernel oops is due to huge_pte_offset(mm, pvmw->address, page_size(page)) ends up indexing hstate[] with order-0 tail page that leads to a NULL hstate pointer being returned for "h->order" dereference. Orabug: 38024577 Signed-off-by: Jane Chu <[email protected]> Reviewed-by: William Roche <[email protected]> Signed-off-by: Vijayendra Suman <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent 0d10899 commit 94a3c29

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

mm/page_vma_mapped.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,19 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
165165
return not_found(pvmw);
166166

167167
if (unlikely(PageHuge(page))) {
168+
struct hstate *hstate = hstate_vma(pvmw->vma);
169+
unsigned long size = huge_page_size(hstate);
170+
168171
/* The only possible mapping was handled on last iteration */
169172
if (pvmw->pte)
170173
return not_found(pvmw);
171174

172175
/* when pud is not present, pte will be NULL */
173-
pvmw->pte = huge_pte_offset(mm, pvmw->address, page_size(page));
176+
pvmw->pte = huge_pte_offset(mm, pvmw->address, size);
174177
if (!pvmw->pte)
175178
return false;
176179

177-
pvmw->ptl = huge_pte_lockptr(page_hstate(page), mm, pvmw->pte);
180+
pvmw->ptl = huge_pte_lockptr(hstate, mm, pvmw->pte);
178181
spin_lock(pvmw->ptl);
179182
if (!check_pte(pvmw))
180183
return not_found(pvmw);

0 commit comments

Comments
 (0)