From 0ed7a4455e0927ca29090e6e127aa2487c0f91ba Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Tue, 1 Dec 2015 17:57:02 +0100
Subject: [PATCH 071/398] mm/rmap: retry lock check in anon_vma_free()

anon_vma_free() checks if the rwsem is locked and if so performs a
rw lock + unlock operation. It seems the purpose is to flush the current
reader out.
From testing it seems that after the anon_vma_unlock_write() there is
the rt_mutex's owner field has the waiter bit set. It does seem right to
leave and kfree() that memory if there is still a waiter on that lock.
The msleep() is there in case the anon_vma_free() caller has the highest
priority and the waiter never gets scheduled.

XXX

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 mm/rmap.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index 1bceb49aa214..c96041a06d0d 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -89,8 +89,10 @@ static inline struct anon_vma *anon_vma_alloc(void)
 	return anon_vma;
 }
 
-static inline void anon_vma_free(struct anon_vma *anon_vma)
+#include <linux/delay.h>
+static void anon_vma_free(struct anon_vma *anon_vma)
 {
+	int cnt = 0;
 	VM_BUG_ON(atomic_read(&anon_vma->refcount));
 
 	/*
@@ -111,9 +113,17 @@ static inline void anon_vma_free(struct anon_vma *anon_vma)
 	 * happen _before_ what follows.
 	 */
 	might_sleep();
+retry:
 	if (rwsem_is_locked(&anon_vma->root->rwsem)) {
 		anon_vma_lock_write(anon_vma);
 		anon_vma_unlock_write(anon_vma);
+
+		if (rwsem_is_locked(&anon_vma->root->rwsem)) {
+			cnt++;
+			if (cnt > 3)
+				msleep(1);
+		}
+		goto retry;
 	}
 
 	kmem_cache_free(anon_vma_cachep, anon_vma);
-- 
2.14.4

