diff options
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 64 |
1 files changed, 15 insertions, 49 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index aedc1b183cf9..df2e7dd5ff17 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -3238,7 +3238,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, | |||
3238 | struct page *ptepage; | 3238 | struct page *ptepage; |
3239 | unsigned long addr; | 3239 | unsigned long addr; |
3240 | int cow; | 3240 | int cow; |
3241 | struct address_space *mapping = vma->vm_file->f_mapping; | ||
3242 | struct hstate *h = hstate_vma(vma); | 3241 | struct hstate *h = hstate_vma(vma); |
3243 | unsigned long sz = huge_page_size(h); | 3242 | unsigned long sz = huge_page_size(h); |
3244 | struct mmu_notifier_range range; | 3243 | struct mmu_notifier_range range; |
@@ -3250,23 +3249,13 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, | |||
3250 | mmu_notifier_range_init(&range, src, vma->vm_start, | 3249 | mmu_notifier_range_init(&range, src, vma->vm_start, |
3251 | vma->vm_end); | 3250 | vma->vm_end); |
3252 | mmu_notifier_invalidate_range_start(&range); | 3251 | mmu_notifier_invalidate_range_start(&range); |
3253 | } else { | ||
3254 | /* | ||
3255 | * For shared mappings i_mmap_rwsem must be held to call | ||
3256 | * huge_pte_alloc, otherwise the returned ptep could go | ||
3257 | * away if part of a shared pmd and another thread calls | ||
3258 | * huge_pmd_unshare. | ||
3259 | */ | ||
3260 | i_mmap_lock_read(mapping); | ||
3261 | } | 3252 | } |
3262 | 3253 | ||
3263 | for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) { | 3254 | for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) { |
3264 | spinlock_t *src_ptl, *dst_ptl; | 3255 | spinlock_t *src_ptl, *dst_ptl; |
3265 | |||
3266 | src_pte = huge_pte_offset(src, addr, sz); | 3256 | src_pte = huge_pte_offset(src, addr, sz); |
3267 | if (!src_pte) | 3257 | if (!src_pte) |
3268 | continue; | 3258 | continue; |
3269 | |||
3270 | dst_pte = huge_pte_alloc(dst, addr, sz); | 3259 | dst_pte = huge_pte_alloc(dst, addr, sz); |
3271 | if (!dst_pte) { | 3260 | if (!dst_pte) { |
3272 | ret = -ENOMEM; | 3261 | ret = -ENOMEM; |
@@ -3337,8 +3326,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, | |||
3337 | 3326 | ||
3338 | if (cow) | 3327 | if (cow) |
3339 | mmu_notifier_invalidate_range_end(&range); | 3328 | mmu_notifier_invalidate_range_end(&range); |
3340 | else | ||
3341 | i_mmap_unlock_read(mapping); | ||
3342 | 3329 | ||
3343 | return ret; | 3330 | return ret; |
3344 | } | 3331 | } |
@@ -3784,18 +3771,14 @@ retry: | |||
3784 | }; | 3771 | }; |
3785 | 3772 | ||
3786 | /* | 3773 | /* |
3787 | * hugetlb_fault_mutex and i_mmap_rwsem must be | 3774 | * hugetlb_fault_mutex must be dropped before |
3788 | * dropped before handling userfault. Reacquire | 3775 | * handling userfault. Reacquire after handling |
3789 | * after handling fault to make calling code simpler. | 3776 | * fault to make calling code simpler. |
3790 | */ | 3777 | */ |
3791 | hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, | 3778 | hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, |
3792 | idx, haddr); | 3779 | idx, haddr); |
3793 | mutex_unlock(&hugetlb_fault_mutex_table[hash]); | 3780 | mutex_unlock(&hugetlb_fault_mutex_table[hash]); |
3794 | i_mmap_unlock_read(mapping); | ||
3795 | |||
3796 | ret = handle_userfault(&vmf, VM_UFFD_MISSING); | 3781 | ret = handle_userfault(&vmf, VM_UFFD_MISSING); |
3797 | |||
3798 | i_mmap_lock_read(mapping); | ||
3799 | mutex_lock(&hugetlb_fault_mutex_table[hash]); | 3782 | mutex_lock(&hugetlb_fault_mutex_table[hash]); |
3800 | goto out; | 3783 | goto out; |
3801 | } | 3784 | } |
@@ -3943,11 +3926,6 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3943 | 3926 | ||
3944 | ptep = huge_pte_offset(mm, haddr, huge_page_size(h)); | 3927 | ptep = huge_pte_offset(mm, haddr, huge_page_size(h)); |
3945 | if (ptep) { | 3928 | if (ptep) { |
3946 | /* | ||
3947 | * Since we hold no locks, ptep could be stale. That is | ||
3948 | * OK as we are only making decisions based on content and | ||
3949 | * not actually modifying content here. | ||
3950 | */ | ||
3951 | entry = huge_ptep_get(ptep); | 3929 | entry = huge_ptep_get(ptep); |
3952 | if (unlikely(is_hugetlb_entry_migration(entry))) { | 3930 | if (unlikely(is_hugetlb_entry_migration(entry))) { |
3953 | migration_entry_wait_huge(vma, mm, ptep); | 3931 | migration_entry_wait_huge(vma, mm, ptep); |
@@ -3955,31 +3933,20 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3955 | } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) | 3933 | } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) |
3956 | return VM_FAULT_HWPOISON_LARGE | | 3934 | return VM_FAULT_HWPOISON_LARGE | |
3957 | VM_FAULT_SET_HINDEX(hstate_index(h)); | 3935 | VM_FAULT_SET_HINDEX(hstate_index(h)); |
3936 | } else { | ||
3937 | ptep = huge_pte_alloc(mm, haddr, huge_page_size(h)); | ||
3938 | if (!ptep) | ||
3939 | return VM_FAULT_OOM; | ||
3958 | } | 3940 | } |
3959 | 3941 | ||
3960 | /* | ||
3961 | * Acquire i_mmap_rwsem before calling huge_pte_alloc and hold | ||
3962 | * until finished with ptep. This prevents huge_pmd_unshare from | ||
3963 | * being called elsewhere and making the ptep no longer valid. | ||
3964 | * | ||
3965 | * ptep could have already be assigned via huge_pte_offset. That | ||
3966 | * is OK, as huge_pte_alloc will return the same value unless | ||
3967 | * something changed. | ||
3968 | */ | ||
3969 | mapping = vma->vm_file->f_mapping; | 3942 | mapping = vma->vm_file->f_mapping; |
3970 | i_mmap_lock_read(mapping); | 3943 | idx = vma_hugecache_offset(h, vma, haddr); |
3971 | ptep = huge_pte_alloc(mm, haddr, huge_page_size(h)); | ||
3972 | if (!ptep) { | ||
3973 | i_mmap_unlock_read(mapping); | ||
3974 | return VM_FAULT_OOM; | ||
3975 | } | ||
3976 | 3944 | ||
3977 | /* | 3945 | /* |
3978 | * Serialize hugepage allocation and instantiation, so that we don't | 3946 | * Serialize hugepage allocation and instantiation, so that we don't |
3979 | * get spurious allocation failures if two CPUs race to instantiate | 3947 | * get spurious allocation failures if two CPUs race to instantiate |
3980 | * the same page in the page cache. | 3948 | * the same page in the page cache. |
3981 | */ | 3949 | */ |
3982 | idx = vma_hugecache_offset(h, vma, haddr); | ||
3983 | hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, idx, haddr); | 3950 | hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, idx, haddr); |
3984 | mutex_lock(&hugetlb_fault_mutex_table[hash]); | 3951 | mutex_lock(&hugetlb_fault_mutex_table[hash]); |
3985 | 3952 | ||
@@ -4067,7 +4034,6 @@ out_ptl: | |||
4067 | } | 4034 | } |
4068 | out_mutex: | 4035 | out_mutex: |
4069 | mutex_unlock(&hugetlb_fault_mutex_table[hash]); | 4036 | mutex_unlock(&hugetlb_fault_mutex_table[hash]); |
4070 | i_mmap_unlock_read(mapping); | ||
4071 | /* | 4037 | /* |
4072 | * Generally it's safe to hold refcount during waiting page lock. But | 4038 | * Generally it's safe to hold refcount during waiting page lock. But |
4073 | * here we just wait to defer the next page fault to avoid busy loop and | 4039 | * here we just wait to defer the next page fault to avoid busy loop and |
@@ -4672,12 +4638,10 @@ void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma, | |||
4672 | * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() | 4638 | * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() |
4673 | * and returns the corresponding pte. While this is not necessary for the | 4639 | * and returns the corresponding pte. While this is not necessary for the |
4674 | * !shared pmd case because we can allocate the pmd later as well, it makes the | 4640 | * !shared pmd case because we can allocate the pmd later as well, it makes the |
4675 | * code much cleaner. | 4641 | * code much cleaner. pmd allocation is essential for the shared case because |
4676 | * | 4642 | * pud has to be populated inside the same i_mmap_rwsem section - otherwise |
4677 | * This routine must be called with i_mmap_rwsem held in at least read mode. | 4643 | * racing tasks could either miss the sharing (see huge_pte_offset) or select a |
4678 | * For hugetlbfs, this prevents removal of any page table entries associated | 4644 | * bad pmd for sharing. |
4679 | * with the address space. This is important as we are setting up sharing | ||
4680 | * based on existing page table entries (mappings). | ||
4681 | */ | 4645 | */ |
4682 | pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) | 4646 | pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) |
4683 | { | 4647 | { |
@@ -4694,6 +4658,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) | |||
4694 | if (!vma_shareable(vma, addr)) | 4658 | if (!vma_shareable(vma, addr)) |
4695 | return (pte_t *)pmd_alloc(mm, pud, addr); | 4659 | return (pte_t *)pmd_alloc(mm, pud, addr); |
4696 | 4660 | ||
4661 | i_mmap_lock_write(mapping); | ||
4697 | vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) { | 4662 | vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) { |
4698 | if (svma == vma) | 4663 | if (svma == vma) |
4699 | continue; | 4664 | continue; |
@@ -4723,6 +4688,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) | |||
4723 | spin_unlock(ptl); | 4688 | spin_unlock(ptl); |
4724 | out: | 4689 | out: |
4725 | pte = (pte_t *)pmd_alloc(mm, pud, addr); | 4690 | pte = (pte_t *)pmd_alloc(mm, pud, addr); |
4691 | i_mmap_unlock_write(mapping); | ||
4726 | return pte; | 4692 | return pte; |
4727 | } | 4693 | } |
4728 | 4694 | ||
@@ -4733,7 +4699,7 @@ out: | |||
4733 | * indicated by page_count > 1, unmap is achieved by clearing pud and | 4699 | * indicated by page_count > 1, unmap is achieved by clearing pud and |
4734 | * decrementing the ref count. If count == 1, the pte page is not shared. | 4700 | * decrementing the ref count. If count == 1, the pte page is not shared. |
4735 | * | 4701 | * |
4736 | * Called with page table lock held and i_mmap_rwsem held in write mode. | 4702 | * called with page table lock held. |
4737 | * | 4703 | * |
4738 | * returns: 1 successfully unmapped a shared pte page | 4704 | * returns: 1 successfully unmapped a shared pte page |
4739 | * 0 the underlying pte page is not shared, or it is the last user | 4705 | * 0 the underlying pte page is not shared, or it is the last user |