blob: 52ec69872c7f2e55d8ac77f17603111881cc2f38 [file] [log] [blame]
From: Jann Horn <jannh@google.com>
Subject: mm-hugetlb-unshare-page-tables-during-vma-split-not-before-v2
Date: Wed, 28 May 2025 19:08:55 +0200
- more verbose locking context explanation (Lorenzo)
- assert file rmap lock held (Lorenzo)
- label bool function argument (Lorenzo)
- more verbose locking context comment (Lorenzo)
Link: https://lkml.kernel.org/r/20250528-hugetlb-fixes-splitrace-v2-1-1329349bad1a@google.com
Fixes: 39dde65c9940 ("[PATCH] shared page table for hugetlb page")
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Signed-off-by: Jann Horn <jannh@google.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
mm/hugetlb.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/mm/hugetlb.c~mm-hugetlb-unshare-page-tables-during-vma-split-not-before-v2
+++ a/mm/hugetlb.c
@@ -5440,6 +5440,7 @@ void hugetlb_split(struct vm_area_struct
* walks (except hardware and gup_fast()).
*/
vma_assert_write_locked(vma);
+ i_mmap_assert_write_locked(vma->vm_file->f_mapping);
if (addr & ~PUD_MASK) {
unsigned long floor = addr & PUD_MASK;
@@ -5456,7 +5457,7 @@ void hugetlb_split(struct vm_area_struct
* table walks, which are not possible thanks to the
* locks held by our caller.
*/
- hugetlb_unshare_pmds(vma, floor, ceil, false);
+ hugetlb_unshare_pmds(vma, floor, ceil, /* take_locks = */ false);
}
}
}
@@ -7900,6 +7901,8 @@ void move_hugetlb_state(struct folio *ol
/*
* If @take_locks is false, the caller must ensure that no concurrent page table
* access can happen (except for gup_fast() and hardware page walks).
+ * If @take_locks is true, we take the hugetlb VMA lock (to lock out things like
+ * concurrent page fault handling) and the file rmap lock.
*/
static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
unsigned long start,
@@ -7961,7 +7964,8 @@ static void hugetlb_unshare_pmds(struct
void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
{
hugetlb_unshare_pmds(vma, ALIGN(vma->vm_start, PUD_SIZE),
- ALIGN_DOWN(vma->vm_end, PUD_SIZE), true);
+ ALIGN_DOWN(vma->vm_end, PUD_SIZE),
+ /* take_locks = */ true);
}
/*
_