hugetlb: Make unmap_ref_private multi-size-aware
Subsystems (2)
Oops. Part of the hugetlb private reservation code was not fully converted to use hstates. When a huge page must be unmapped from VMAs due to a failed COW, HPAGE_SIZE is used in the call to unmap_hugepage_range() regardless of the page size being used. This works if the VMA is using the default huge page size. Otherwise we might unmap too much, too little, or trigger a BUG_ON. Rare but serious -- fix it.
Signed-off-by Adam Litke <[email protected]>
mm/hugetlb.c +3 -2
@@ -1751,6 +1751,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,static int unmap_ref_private (struct mm_struct *mm,struct vm_area_struct *vma,struct page *page,unsigned long address) { +struct hstate *h =hstate_vma (vma);struct vm_area_struct *iter_vma;struct address_space *mapping;struct prio_tree_iter iter;
@@ -1760,7 +1761,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,* vm_pgoff is in PAGE_SIZE units, hence the different calculation * from page cache lookup which is in HPAGE_SIZE units. */ - address = address &huge_page_mask (hstate_vma (vma)); + address = address &huge_page_mask (h); pgoff = ((address - vma->vm_start) >>PAGE_SHIFT ) + (vma->vm_pgoff >>PAGE_SHIFT ); mapping = (struct address_space *)page_private (page);
@@ -1779,7 +1780,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,*/ if (!is_vma_resv_set (iter_vma,HPAGE_RESV_OWNER ))unmap_hugepage_range (iter_vma, - address, address +HPAGE_SIZE , + address, address +huge_page_size (h), page); }
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>