]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - mm/memcontrol.c
memcgroup: fix zone isolation OOM
[linux-2.6.git] / mm / memcontrol.c
index 128f45c16fa6626ac33813fdaefc239c18e9967f..9793873d5a9035c5987c0e301298479e9b21a698 100644 (file)
@@ -250,7 +250,7 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
        unsigned long scan;
        LIST_HEAD(pc_list);
        struct list_head *src;
-       struct page_cgroup *pc;
+       struct page_cgroup *pc, *tmp;
 
        if (active)
                src = &mem_cont->active_list;
@@ -258,19 +258,22 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
                src = &mem_cont->inactive_list;
 
        spin_lock(&mem_cont->lru_lock);
-       for (scan = 0; scan < nr_to_scan && !list_empty(src); scan++) {
-               pc = list_entry(src->prev, struct page_cgroup, lru);
+       scan = 0;
+       list_for_each_entry_safe_reverse(pc, tmp, src, lru) {
+               if (scan >= nr_to_scan)
+                       break;
                page = pc->page;
                VM_BUG_ON(!pc);
 
+               if (unlikely(!PageLRU(page)))
+                       continue;
+
                if (PageActive(page) && !active) {
                        __mem_cgroup_move_lists(pc, true);
-                       scan--;
                        continue;
                }
                if (!PageActive(page) && active) {
                        __mem_cgroup_move_lists(pc, false);
-                       scan--;
                        continue;
                }
 
@@ -281,13 +284,8 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
                if (page_zone(page) != z)
                        continue;
 
-               /*
-                * Check if the meta page went away from under us
-                */
-               if (!list_empty(&pc->lru))
-                       list_move(&pc->lru, &pc_list);
-               else
-                       continue;
+               scan++;
+               list_move(&pc->lru, &pc_list);
 
                if (__isolate_lru_page(page, mode) == 0) {
                        list_move(&page->lru, dst);