aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorDaisuke Nishimura <nishimura@mxp.nes.nec.co.jp>2011-01-13 18:46:56 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:43 -0500
commit152c9ccb75548c027fa3103efa4fa4e19a345449 (patch)
treed22e8f71b3e0689fc0e3ae21609ae1abe5bc4d2f /mm/memcontrol.c
parentec1685109f1314a30919489ef2800ed626a38c1e (diff)
thp: transhuge-memcg: commit tail pages at charge
By this patch, when a transparent hugepage is charged, not only the head page but also all the tail pages are committed, IOW pc->mem_cgroup and pc->flags of tail pages are set. Without this patch: - Tail pages are not linked to any memcg's LRU at splitting. This causes many problems, for example, the charged memcg's directory can never be rmdir'ed because it doesn't have enough pages to scan to make the usage decrease to 0. - "rss" field in memory.stat would be incorrect. Moreover, usage_in_bytes in root cgroup is calculated by the stat not by res_counter(since 2.6.32), it would be incorrect too. Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Signed-off-by: Andrea Arcangeli <aarcange@redhat.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.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 356d4964fe95..a1bb59d4c9d0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2094,23 +2094,10 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
2094 * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be 2094 * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be
2095 * USED state. If already USED, uncharge and return. 2095 * USED state. If already USED, uncharge and return.
2096 */ 2096 */
2097 2097static void ____mem_cgroup_commit_charge(struct mem_cgroup *mem,
2098static void __mem_cgroup_commit_charge(struct mem_cgroup *mem, 2098 struct page_cgroup *pc,
2099 struct page_cgroup *pc, 2099 enum charge_type ctype)
2100 enum charge_type ctype,
2101 int page_size)
2102{ 2100{
2103 /* try_charge() can return NULL to *memcg, taking care of it. */
2104 if (!mem)
2105 return;
2106
2107 lock_page_cgroup(pc);
2108 if (unlikely(PageCgroupUsed(pc))) {
2109 unlock_page_cgroup(pc);
2110 mem_cgroup_cancel_charge(mem, page_size);
2111 return;
2112 }
2113
2114 pc->mem_cgroup = mem; 2101 pc->mem_cgroup = mem;
2115 /* 2102 /*
2116 * We access a page_cgroup asynchronously without lock_page_cgroup(). 2103 * We access a page_cgroup asynchronously without lock_page_cgroup().
@@ -2135,6 +2122,33 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
2135 } 2122 }
2136 2123
2137 mem_cgroup_charge_statistics(mem, pc, true); 2124 mem_cgroup_charge_statistics(mem, pc, true);
2125}
2126
2127static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
2128 struct page_cgroup *pc,
2129 enum charge_type ctype,
2130 int page_size)
2131{
2132 int i;
2133 int count = page_size >> PAGE_SHIFT;
2134
2135 /* try_charge() can return NULL to *memcg, taking care of it. */
2136 if (!mem)
2137 return;
2138
2139 lock_page_cgroup(pc);
2140 if (unlikely(PageCgroupUsed(pc))) {
2141 unlock_page_cgroup(pc);
2142 mem_cgroup_cancel_charge(mem, page_size);
2143 return;
2144 }
2145
2146 /*
2147 * we don't need page_cgroup_lock about tail pages, becase they are not
2148 * accessed by any other context at this point.
2149 */
2150 for (i = 0; i < count; i++)
2151 ____mem_cgroup_commit_charge(mem, pc + i, ctype);
2138 2152
2139 unlock_page_cgroup(pc); 2153 unlock_page_cgroup(pc);
2140 /* 2154 /*
@@ -2532,6 +2546,8 @@ direct_uncharge:
2532static struct mem_cgroup * 2546static struct mem_cgroup *
2533__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) 2547__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
2534{ 2548{
2549 int i;
2550 int count;
2535 struct page_cgroup *pc; 2551 struct page_cgroup *pc;
2536 struct mem_cgroup *mem = NULL; 2552 struct mem_cgroup *mem = NULL;
2537 int page_size = PAGE_SIZE; 2553 int page_size = PAGE_SIZE;
@@ -2545,6 +2561,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
2545 if (PageTransHuge(page)) 2561 if (PageTransHuge(page))
2546 page_size <<= compound_order(page); 2562 page_size <<= compound_order(page);
2547 2563
2564 count = page_size >> PAGE_SHIFT;
2548 /* 2565 /*
2549 * Check if our page_cgroup is valid 2566 * Check if our page_cgroup is valid
2550 */ 2567 */
@@ -2577,7 +2594,8 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
2577 break; 2594 break;
2578 } 2595 }
2579 2596
2580 mem_cgroup_charge_statistics(mem, pc, false); 2597 for (i = 0; i < count; i++)
2598 mem_cgroup_charge_statistics(mem, pc + i, false);
2581 2599
2582 ClearPageCgroupUsed(pc); 2600 ClearPageCgroupUsed(pc);
2583 /* 2601 /*