Skip to contentSkip to conversation

Patch "mm/list_lru.c: fix list_lru_count_node() to be race free" has been added to the 4.11-stable tree

PATCH [email protected] 1 participant 1 message Jul 18, 2017

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

mm/list_lru.c: fix list_lru_count_node() to be race free

to the 4.11-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
mm-list_lru.c-fix-list_lru_count_node-to-be-race-free.patch
and it can be found in the queue-4.11 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 2c80cd57c74339889a8752b20862a16c28929c3a Mon Sep 17 00:00:00 2001

From: Sahitya Tummala <[email protected]>
Date: Mon, 10 Jul 2017 15:49:57 -0700
Subject: mm/list_lru.c: fix list_lru_count_node() to be race free

From: Sahitya Tummala <[email protected]>

commit 2c80cd57c74339889a8752b20862a16c28929c3a upstream.

list_lru_count_node() iterates over all memcgs to get the total number of entries on the node but it can race with memcg_drain_all_list_lrus(), which migrates the entries from a dead cgroup to another. This can return incorrect number of entries from list_lru_count_node().

Fix this by keeping track of entries per node and simply return it in list_lru_count_node().

---
 include/linux/list_lru.h |    1 +
 mm/list_lru.c            |   14 ++++++--------
 2 files changed, 7 insertions(+), 8 deletions(-)
include/linux/list_lru.h +1 -0
@@ -44,6 +44,7 @@ struct list_lru_node {
 	/* for cgroup aware lrus points to per cgroup lists, otherwise NULL */
 	struct list_lru_memcg	*memcg_lrus;
 #endif
+	long nr_items;
 } ____cacheline_aligned_in_smp;
 
 struct list_lru {
mm/list_lru.c +6 -8
@@ -117,6 +117,7 @@ bool list_lru_add(struct list_lru *lru,
 		l = list_lru_from_kmem(nlru, item);
 		list_add_tail(item, &l->list);
 		l->nr_items++;
+		nlru->nr_items++;
 		spin_unlock(&nlru->lock);
 		return true;
 	}
@@ -136,6 +137,7 @@ bool list_lru_del(struct list_lru *lru,
 		l = list_lru_from_kmem(nlru, item);
 		list_del_init(item);
 		l->nr_items--;
+		nlru->nr_items--;
 		spin_unlock(&nlru->lock);
 		return true;
 	}
@@ -183,15 +185,10 @@ EXPORT_SYMBOL_GPL(list_lru_count_one);
 
 unsigned long list_lru_count_node(struct list_lru *lru, int nid)
 {
-	long count = 0;
-	int memcg_idx;
+	struct list_lru_node *nlru;
 
-	count += __list_lru_count_one(lru, nid, -1);
-	if (list_lru_memcg_aware(lru)) {
-		for_each_memcg_cache_index(memcg_idx)
-			count += __list_lru_count_one(lru, nid, memcg_idx);
-	}
-	return count;
+	nlru = &lru->node[nid];
+	return nlru->nr_items;
 }
 EXPORT_SYMBOL_GPL(list_lru_count_node);
 
@@ -226,6 +223,7 @@ restart:
 			assert_spin_locked(&nlru->lock);
 		case LRU_REMOVED:
 			isolated++;
+			nlru->nr_items--;
 			/*
 			 * If the lru lock has been dropped, our list
 			 * traversal is now invalid and so we have to

Patches currently in stable-queue which might be from [email protected] are

queue-4.11/mm-list_lru.c-fix-list_lru_count_node-to-be-race-free.patch queue-4.11/fs-dcache.c-fix-spin-lockup-issue-on-nlru-lock.patch