mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 12:52:29 -04:00
hugetlb: only adjust reservation during unmapping if mapcount is 0
Sincedf7a6d1f64, __unmap_hugepage_range can adjust reservations. In the case of folio mapped in both a parent and a child, if the parent unmaps the range first, the reservation adjustment will result in an underflow of the reserved count. Once the child unmaps the range, the count is restored. Change __unmap_hugepage_range() to check the mapcount before adjusting the reservation. Link: https://lore.kernel.org/all/alEJkwn5VlTTH_ZX@bender.morinfr.org/ Link: https://lore.kernel.org/amkC_1Ya6OiUoiLZ@bender.morinfr.org Fixes:df7a6d1f64("mm/hugetlb: restore the reservation if needed") Signed-off-by: Guillaume Morin <guillaume@morinfr.org> Reviewed-by: Breno Leitao <leitao@debian.org> Reviewed-by: Rik van Riel <riel@surriel.com> Cc: Muchun Song <muchun.song@linux.dev> Cc: David Hildenbrand <david@kernel.org> Cc: Oscar Salvador <osalvador@suse.de> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
62e39381b7
commit
5120b1e048
@@ -5218,6 +5218,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
|
||||
bool adjust_reservation;
|
||||
unsigned long last_addr_mask;
|
||||
|
||||
i_mmap_assert_write_locked(vma->vm_file->f_mapping);
|
||||
WARN_ON(!is_vm_hugetlb_page(vma));
|
||||
BUG_ON(start & ~huge_page_mask(h));
|
||||
BUG_ON(end & ~huge_page_mask(h));
|
||||
@@ -5309,7 +5310,10 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
|
||||
|
||||
/*
|
||||
* Restore the reservation for anonymous page, otherwise the
|
||||
* backing page could be stolen by someone.
|
||||
* backing page could be stolen by someone. Restore only on the
|
||||
* last unmap, otherwise the owner could empty its resv map
|
||||
* while the folio is still mapped by a child. Note that holding
|
||||
* i_mmap_lock_write is needed to check the number of mappings.
|
||||
* If there we are freeing a surplus, do not set the restore
|
||||
* reservation bit.
|
||||
*/
|
||||
@@ -5317,7 +5321,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
|
||||
|
||||
spin_lock_irq(&hugetlb_lock);
|
||||
if (!h->surplus_huge_pages && __vma_private_lock(vma) &&
|
||||
folio_test_anon(folio)) {
|
||||
!folio_mapped(folio) && folio_test_anon(folio)) {
|
||||
folio_set_hugetlb_restore_reserve(folio);
|
||||
/* Reservation to be adjusted after the spin lock */
|
||||
adjust_reservation = true;
|
||||
|
||||
Reference in New Issue
Block a user