aboutsummaryrefslogtreecommitdiffstats
path: root/mm/list_lru.c
diff options
context:
space:
mode:
authorVladimir Davydov <vdavydov@parallels.com>2015-02-12 17:59:35 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-12 21:54:10 -0500
commit3f97b163207c67a3b35931494ad3db1de66356f0 (patch)
tree012012aafb687ebfb7e794e2bcd0c1728212fafc /mm/list_lru.c
parent2a4db7eb9391a544ff58f4fa11d35246e87c87af (diff)
list_lru: add helpers to isolate items
Currently, the isolate callback passed to the list_lru_walk family of functions is supposed to just delete an item from the list upon returning LRU_REMOVED or LRU_REMOVED_RETRY, while nr_items counter is fixed by __list_lru_walk_one after the callback returns. Since the callback is allowed to drop the lock after removing an item (it has to return LRU_REMOVED_RETRY then), the nr_items can be less than the actual number of elements on the list even if we check them under the lock. This makes it difficult to move items from one list_lru_one to another, which is required for per-memcg list_lru reparenting - we can't just splice the lists, we have to move entries one by one. This patch therefore introduces helpers that must be used by callback functions to isolate items instead of raw list_del/list_move. These are list_lru_isolate and list_lru_isolate_move. They not only remove the entry from the list, but also fix the nr_items counter, making sure nr_items always reflects the actual number of elements on the list if checked under the appropriate lock. Signed-off-by: Vladimir Davydov <vdavydov@parallels.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: Tejun Heo <tj@kernel.org> Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Dave Chinner <david@fromorbit.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/list_lru.c')
-rw-r--r--mm/list_lru.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 79aee70c3b9d..8d9d168c6c38 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -132,6 +132,21 @@ bool list_lru_del(struct list_lru *lru, struct list_head *item)
132} 132}
133EXPORT_SYMBOL_GPL(list_lru_del); 133EXPORT_SYMBOL_GPL(list_lru_del);
134 134
135void list_lru_isolate(struct list_lru_one *list, struct list_head *item)
136{
137 list_del_init(item);
138 list->nr_items--;
139}
140EXPORT_SYMBOL_GPL(list_lru_isolate);
141
142void list_lru_isolate_move(struct list_lru_one *list, struct list_head *item,
143 struct list_head *head)
144{
145 list_move(item, head);
146 list->nr_items--;
147}
148EXPORT_SYMBOL_GPL(list_lru_isolate_move);
149
135static unsigned long __list_lru_count_one(struct list_lru *lru, 150static unsigned long __list_lru_count_one(struct list_lru *lru,
136 int nid, int memcg_idx) 151 int nid, int memcg_idx)
137{ 152{
@@ -194,13 +209,11 @@ restart:
194 break; 209 break;
195 --*nr_to_walk; 210 --*nr_to_walk;
196 211
197 ret = isolate(item, &nlru->lock, cb_arg); 212 ret = isolate(item, l, &nlru->lock, cb_arg);
198 switch (ret) { 213 switch (ret) {
199 case LRU_REMOVED_RETRY: 214 case LRU_REMOVED_RETRY:
200 assert_spin_locked(&nlru->lock); 215 assert_spin_locked(&nlru->lock);
201 case LRU_REMOVED: 216 case LRU_REMOVED:
202 l->nr_items--;
203 WARN_ON_ONCE(l->nr_items < 0);
204 isolated++; 217 isolated++;
205 /* 218 /*
206 * If the lru lock has been dropped, our list 219 * If the lru lock has been dropped, our list