aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2008-02-07 03:14:12 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 11:42:20 -0500
commit436c6541b13a73790646eb11429bdc8ee50eec41 (patch)
tree45be274e89e7b8db83a98eb3c07031d066e13b16 /mm/memcontrol.c
parentff7283fa3a66823933991ad55a558a3a01d5ab27 (diff)
memcgroup: fix zone isolation OOM
mem_cgroup_charge_common shows a tendency to OOM without good reason, when a memhog goes well beyond its rss limit but with plenty of swap available. Seen on x86 but not on PowerPC; seen when the next patch omits swapcache from memcgroup, but we presume it can happen without. mem_cgroup_isolate_pages is not quite satisfying reclaim's criteria for OOM avoidance. Already it has to scan beyond the nr_to_scan limit when it finds a !LRU page or an active page when handling inactive or an inactive page when handling active. It needs to do exactly the same when it finds a page from the wrong zone (the x86 tests had two zones, the PowerPC tests had only one). Don't increment scan and then decrement it in these cases, just move the incrementation down. Fix recent off-by-one when checking against nr_to_scan. Cut out "Check if the meta page went away from under us", presumably left over from early debugging: no amount of such checks could save us if this list really were being updated without locking. This change does make the unlimited scan while holding two spinlocks even worse - bad for latency and bad for containment; but that's a separate issue which is better left to be fixed a little later. Signed-off-by: Hugh Dickins <hugh@veritas.com> Cc: Pavel Emelianov <xemul@openvz.org> Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Paul Menage <menage@google.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Cc: Kirill Korotaev <dev@sw.ru> Cc: Herbert Poetzl <herbert@13thfloor.at> Cc: David Rientjes <rientjes@google.com> Cc: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c17
1 files changed, 4 insertions, 13 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e8493fb2d69e..9793873d5a90 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -260,24 +260,20 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
260 spin_lock(&mem_cont->lru_lock); 260 spin_lock(&mem_cont->lru_lock);
261 scan = 0; 261 scan = 0;
262 list_for_each_entry_safe_reverse(pc, tmp, src, lru) { 262 list_for_each_entry_safe_reverse(pc, tmp, src, lru) {
263 if (scan++ > nr_to_scan) 263 if (scan >= nr_to_scan)
264 break; 264 break;
265 page = pc->page; 265 page = pc->page;
266 VM_BUG_ON(!pc); 266 VM_BUG_ON(!pc);
267 267
268 if (unlikely(!PageLRU(page))) { 268 if (unlikely(!PageLRU(page)))
269 scan--;
270 continue; 269 continue;
271 }
272 270
273 if (PageActive(page) && !active) { 271 if (PageActive(page) && !active) {
274 __mem_cgroup_move_lists(pc, true); 272 __mem_cgroup_move_lists(pc, true);
275 scan--;
276 continue; 273 continue;
277 } 274 }
278 if (!PageActive(page) && active) { 275 if (!PageActive(page) && active) {
279 __mem_cgroup_move_lists(pc, false); 276 __mem_cgroup_move_lists(pc, false);
280 scan--;
281 continue; 277 continue;
282 } 278 }
283 279
@@ -288,13 +284,8 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
288 if (page_zone(page) != z) 284 if (page_zone(page) != z)
289 continue; 285 continue;
290 286
291 /* 287 scan++;
292 * Check if the meta page went away from under us 288 list_move(&pc->lru, &pc_list);
293 */
294 if (!list_empty(&pc->lru))
295 list_move(&pc->lru, &pc_list);
296 else
297 continue;
298 289
299 if (__isolate_lru_page(page, mode) == 0) { 290 if (__isolate_lru_page(page, mode) == 0) {
300 list_move(&page->lru, dst); 291 list_move(&page->lru, dst);