aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2011-01-20 17:44:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-20 20:02:06 -0500
commitece35ca810326946ddc930c43356312ad5de44d4 (patch)
tree7e9138fbd0da696f695b45dddd8baa587bd284a4
parentca3e021417eed30ec2b64ce88eb0acf64aa9bc29 (diff)
memcg: fix LRU accounting with THP
memory cgroup's LRU stat should take care of size of pages because Transparent Hugepage inserts hugepage into LRU. If this value is the number wrong, memory reclaim will not work well. Note: only head page of THP's huge page is linked into LRU. Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/memcontrol.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 848b42195e5b..7a94ef6b35e2 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -814,7 +814,8 @@ void mem_cgroup_del_lru_list(struct page *page, enum lru_list lru)
814 * removed from global LRU. 814 * removed from global LRU.
815 */ 815 */
816 mz = page_cgroup_zoneinfo(pc); 816 mz = page_cgroup_zoneinfo(pc);
817 MEM_CGROUP_ZSTAT(mz, lru) -= 1; 817 /* huge page split is done under lru_lock. so, we have no races. */
818 MEM_CGROUP_ZSTAT(mz, lru) -= 1 << compound_order(page);
818 if (mem_cgroup_is_root(pc->mem_cgroup)) 819 if (mem_cgroup_is_root(pc->mem_cgroup))
819 return; 820 return;
820 VM_BUG_ON(list_empty(&pc->lru)); 821 VM_BUG_ON(list_empty(&pc->lru));
@@ -865,7 +866,8 @@ void mem_cgroup_add_lru_list(struct page *page, enum lru_list lru)
865 return; 866 return;
866 867
867 mz = page_cgroup_zoneinfo(pc); 868 mz = page_cgroup_zoneinfo(pc);
868 MEM_CGROUP_ZSTAT(mz, lru) += 1; 869 /* huge page split is done under lru_lock. so, we have no races. */
870 MEM_CGROUP_ZSTAT(mz, lru) += 1 << compound_order(page);
869 SetPageCgroupAcctLRU(pc); 871 SetPageCgroupAcctLRU(pc);
870 if (mem_cgroup_is_root(pc->mem_cgroup)) 872 if (mem_cgroup_is_root(pc->mem_cgroup))
871 return; 873 return;
@@ -2152,14 +2154,26 @@ void mem_cgroup_split_huge_fixup(struct page *head, struct page *tail)
2152 unsigned long flags; 2154 unsigned long flags;
2153 2155
2154 /* 2156 /*
2155 * We have no races witch charge/uncharge but will have races with 2157 * We have no races with charge/uncharge but will have races with
2156 * page state accounting. 2158 * page state accounting.
2157 */ 2159 */
2158 move_lock_page_cgroup(head_pc, &flags); 2160 move_lock_page_cgroup(head_pc, &flags);
2159 2161
2160 tail_pc->mem_cgroup = head_pc->mem_cgroup; 2162 tail_pc->mem_cgroup = head_pc->mem_cgroup;
2161 smp_wmb(); /* see __commit_charge() */ 2163 smp_wmb(); /* see __commit_charge() */
2162 /* we don't need to copy all flags...*/ 2164 if (PageCgroupAcctLRU(head_pc)) {
2165 enum lru_list lru;
2166 struct mem_cgroup_per_zone *mz;
2167
2168 /*
2169 * LRU flags cannot be copied because we need to add tail
2170 *.page to LRU by generic call and our hook will be called.
2171 * We hold lru_lock, then, reduce counter directly.
2172 */
2173 lru = page_lru(head);
2174 mz = page_cgroup_zoneinfo(head_pc);
2175 MEM_CGROUP_ZSTAT(mz, lru) -= 1;
2176 }
2163 tail_pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT; 2177 tail_pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT;
2164 move_unlock_page_cgroup(head_pc, &flags); 2178 move_unlock_page_cgroup(head_pc, &flags);
2165} 2179}