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

Submitted by Andrey Ryabinin on May 17, 2019, 1:08 p.m.

Details

Message ID 20190517130802.4596-1-aryabinin@virtuozzo.com
State New
Series "Series without cover letter"
Headers show

Commit Message

Andrey Ryabinin May 17, 2019, 1:08 p.m.
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@virtuozzo.com>
---
 mm/workingset.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

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;
 }
 
 /**