| 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); |
| } |
| |
| /* |
| _ |