diff --git a/include/linux/mm.h b/include/linux/mm.h index d7b71bdde2fc..c2616ff79bfd 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -711,6 +711,14 @@ static inline void vma_assert_write_locked(struct vm_area_struct *vma) VM_BUG_ON_VMA(!__is_vma_write_locked(vma, &mm_lock_seq), vma); } +static inline void vma_mark_detached(struct vm_area_struct *vma, bool detached) +{ + /* When detaching vma should be write-locked */ + if (detached) + vma_assert_write_locked(vma); + vma->detached = detached; +} + #else /* CONFIG_PER_VMA_LOCK */ static inline void vma_init_lock(struct vm_area_struct *vma) {} @@ -721,6 +729,8 @@ static inline void vma_start_write(struct vm_area_struct *vma) {} static inline bool vma_try_start_write(struct vm_area_struct *vma) { return true; } static inline void vma_assert_write_locked(struct vm_area_struct *vma) {} +static inline void vma_mark_detached(struct vm_area_struct *vma, + bool detached) {} #endif /* CONFIG_PER_VMA_LOCK */ @@ -732,6 +742,7 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm) vma->vm_mm = mm; vma->vm_ops = &dummy_vm_ops; INIT_LIST_HEAD(&vma->anon_vma_chain); + vma_mark_detached(vma, false); vma_init_lock(vma); } diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 5347db7ed621..5956bf1cfece 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -476,6 +476,9 @@ struct vm_area_struct { #ifdef CONFIG_PER_VMA_LOCK int vm_lock_seq; struct rw_semaphore lock; + + /* Flag to indicate areas detached from the mm->mm_mt tree */ + bool detached; #endif /* diff --git a/mm/mmap.c b/mm/mmap.c index ed1fc3927157..35c6565fc5e3 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -575,6 +575,8 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, vma->vm_pgoff = pgoff; /* Note: mas must be pointing to the expanding VMA */ vma_mas_store(vma, mas); + if (remove_next) + vma_mark_detached(next, true); if (file) { vma_interval_tree_insert(vma, root); @@ -857,6 +859,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, if (remove_next) { again: + vma_mark_detached(next, true); if (file) { uprobe_munmap(next, next->vm_start, next->vm_end); fput(file); @@ -2323,6 +2326,7 @@ static inline int munmap_sidetree(struct vm_area_struct *vma, int count, if (mas_store_gfp(mas_detach, vma, GFP_KERNEL)) return -ENOMEM; + vma_mark_detached(vma, true); if (vma->vm_flags & VM_LOCKED) vma->vm_mm->locked_vm -= vma_pages(vma);