[Devel] [PATCH rh7 1/3] mm/workingset: fix possible with memcg deletion.

Andrey Ryabinin aryabinin at virtuozzo.com
Fri May 17 16:08:00 MSK 2019


workingset_refault() releases RCU lock too soon, before the
memcg_inc_ws_activate() which may result in crash if memcg deletion
runs in parallel with workingset_refault()

Fixes: f6a8b015027e ("ms/mm: workingset: per-cgroup cache thrash detection")
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
 mm/workingset.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/mm/workingset.c b/mm/workingset.c
index 1168cc122828..1d7bdbf7a5d6 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -250,6 +250,7 @@ bool workingset_refault(void *shadow)
 	unsigned long refault;
 	struct zone *zone;
 	int memcgid;
+	bool ret = false;
 
 	unpack_shadow(shadow, &memcgid, &zone, &eviction);
 
@@ -278,7 +279,6 @@ bool workingset_refault(void *shadow)
 	lruvec = mem_cgroup_zone_lruvec(zone, memcg);
 	refault = atomic_long_read(&lruvec->inactive_age);
 	active_file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE);
-	rcu_read_unlock();
 
 	/*
 	 * The unsigned subtraction here gives an accurate distance
@@ -303,9 +303,10 @@ bool workingset_refault(void *shadow)
 	if (refault_distance <= active_file) {
 		memcg_inc_ws_activate(memcg);
 		inc_zone_state(zone, WORKINGSET_ACTIVATE);
-		return true;
+		ret = true;
 	}
-	return false;
+	rcu_read_unlock();
+	return ret;
 }
 
 /**
-- 
2.21.0



More information about the Devel mailing list