ANDROID: mm: Fix VMA ref count after fast-mremap
Since the cmpxchg() to unlock the VMA (reset ref count from -1), is
enclosed in VM_BUG_ON_VMA() it gets compiled out in non-debug builds
(CONFIG_DEBUG_VM=n). This means that any VMA that underwent a fast-remap
will have it's refcount stuck at -1, making it not be eligible for
future speculative faults, and preventing freeing of the VMA.
Bug: 323371343
Bug: 322411509
Change-Id: If5bf61c7d94268700f2c4f096d946201b68abdb8
Signed-off-by: Kalesh Singh <[email protected]>
diff --git a/mm/mremap.c b/mm/mremap.c
index a6484e8..fa90d4b 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -217,7 +217,7 @@ static inline bool trylock_vma_ref_count(struct vm_area_struct *vma)
* If we have the only reference, swap the refcount to -1. This
* will prevent other concurrent references by get_vma() for SPFs.
*/
- return atomic_cmpxchg(&vma->vm_ref_count, 1, -1) == 1;
+ return atomic_cmpxchg_acquire(&vma->vm_ref_count, 1, -1) == 1;
}
/*
@@ -225,12 +225,13 @@ static inline bool trylock_vma_ref_count(struct vm_area_struct *vma)
*/
static inline void unlock_vma_ref_count(struct vm_area_struct *vma)
{
+ int old = atomic_xchg_release(&vma->vm_ref_count, 1);
+
/*
* This should only be called after a corresponding,
* successful trylock_vma_ref_count().
*/
- VM_BUG_ON_VMA(atomic_cmpxchg(&vma->vm_ref_count, -1, 1) != -1,
- vma);
+ VM_BUG_ON_VMA(old != -1, vma);
}
#else /* !CONFIG_SPECULATIVE_PAGE_FAULT */
static inline bool trylock_vma_ref_count(struct vm_area_struct *vma)