Assert there are no holders of VMA lock for reading when it is about to be
destroyed.

Signed-off-by: Suren Baghdasaryan <sur...@google.com>
---
 include/linux/mm.h | 8 ++++++++
 kernel/fork.c      | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 594e835bad9c..c464fc8a514c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -680,6 +680,13 @@ static inline void vma_assert_write_locked(struct 
vm_area_struct *vma)
        VM_BUG_ON_VMA(vma->vm_lock_seq != READ_ONCE(vma->vm_mm->mm_lock_seq), 
vma);
 }
 
+static inline void vma_assert_no_reader(struct vm_area_struct *vma)
+{
+       VM_BUG_ON_VMA(rwsem_is_locked(&vma->lock) &&
+                     vma->vm_lock_seq != READ_ONCE(vma->vm_mm->mm_lock_seq),
+                     vma);
+}
+
 #else /* CONFIG_PER_VMA_LOCK */
 
 static inline void vma_init_lock(struct vm_area_struct *vma) {}
@@ -688,6 +695,7 @@ static inline bool vma_read_trylock(struct vm_area_struct 
*vma)
                { return false; }
 static inline void vma_read_unlock(struct vm_area_struct *vma) {}
 static inline void vma_assert_write_locked(struct vm_area_struct *vma) {}
+static inline void vma_assert_no_reader(struct vm_area_struct *vma) {}
 
 #endif /* CONFIG_PER_VMA_LOCK */
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 1591dd8a0745..6d9f14e55ecf 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -485,6 +485,8 @@ static void __vm_area_free(struct rcu_head *head)
 {
        struct vm_area_struct *vma = container_of(head, struct vm_area_struct,
                                                  vm_rcu);
+       /* The vma should either have no lock holders or be write-locked. */
+       vma_assert_no_reader(vma);
        kmem_cache_free(vm_area_cachep, vma);
 }
 #endif
-- 
2.39.0

Reply via email to