diff options
-rw-r--r-- | mm/hugetlb.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 45e305d182f6..01f3e36caa6c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -93,6 +93,7 @@ struct mutex *hugetlb_fault_mutex_table ____cacheline_aligned_in_smp; static int hugetlb_acct_memory(struct hstate *h, long delta); static void hugetlb_vma_lock_free(struct vm_area_struct *vma); static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma); +static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma); static inline bool subpool_is_free(struct hugepage_subpool *spool) { @@ -5188,8 +5189,7 @@ void __unmap_hugepage_range_final(struct mmu_gather *tlb, * be asynchrously deleted. If the page tables are shared, there * will be issues when accessed by someone else. */ - hugetlb_vma_unlock_write(vma); - hugetlb_vma_lock_free(vma); + __hugetlb_vma_unlock_write_free(vma); i_mmap_unlock_write(vma->vm_file->f_mapping); } @@ -6828,6 +6828,30 @@ void hugetlb_vma_lock_release(struct kref *kref) kfree(vma_lock); } +void __hugetlb_vma_unlock_write_put(struct hugetlb_vma_lock *vma_lock) +{ + struct vm_area_struct *vma = vma_lock->vma; + + /* + * vma_lock structure may or not be released as a result of put, + * it certainly will no longer be attached to vma so clear pointer. + * Semaphore synchronizes access to vma_lock->vma field. + */ + vma_lock->vma = NULL; + vma->vm_private_data = NULL; + up_write(&vma_lock->rw_sema); + kref_put(&vma_lock->refs, hugetlb_vma_lock_release); +} + +static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma) +{ + if (__vma_shareable_flags_pmd(vma)) { + struct hugetlb_vma_lock *vma_lock = vma->vm_private_data; + + __hugetlb_vma_unlock_write_put(vma_lock); + } +} + static void hugetlb_vma_lock_free(struct vm_area_struct *vma) { /* @@ -6839,14 +6863,8 @@ static void hugetlb_vma_lock_free(struct vm_area_struct *vma) if (vma->vm_private_data) { struct hugetlb_vma_lock *vma_lock = vma->vm_private_data; - /* - * vma_lock structure may or not be released, but it - * certainly will no longer be attached to vma so clear - * pointer. - */ - vma_lock->vma = NULL; - kref_put(&vma_lock->refs, hugetlb_vma_lock_release); - vma->vm_private_data = NULL; + down_write(&vma_lock->rw_sema); + __hugetlb_vma_unlock_write_put(vma_lock); } } @@ -6997,6 +7015,10 @@ void hugetlb_vma_lock_release(struct kref *kref) { } +static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma) +{ +} + static void hugetlb_vma_lock_free(struct vm_area_struct *vma) { } |