Skip to content

Commit 152c9cc

Browse files
Daisuke Nishimuratorvalds
authored andcommitted
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 <[email protected]> Signed-off-by: Andrea Arcangeli <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent ec16851 commit 152c9cc

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

mm/memcontrol.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,23 +2094,10 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
20942094
* commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be
20952095
* USED state. If already USED, uncharge and return.
20962096
*/
2097-
2098-
static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
2099-
struct page_cgroup *pc,
2100-
enum charge_type ctype,
2101-
int page_size)
2097+
static void ____mem_cgroup_commit_charge(struct mem_cgroup *mem,
2098+
struct page_cgroup *pc,
2099+
enum charge_type ctype)
21022100
{
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-
21142101
pc->mem_cgroup = mem;
21152102
/*
21162103
* We access a page_cgroup asynchronously without lock_page_cgroup().
@@ -2135,6 +2122,33 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
21352122
}
21362123

21372124
mem_cgroup_charge_statistics(mem, pc, true);
2125+
}
2126+
2127+
static 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);
21382152

21392153
unlock_page_cgroup(pc);
21402154
/*
@@ -2532,6 +2546,8 @@ __do_uncharge(struct mem_cgroup *mem, const enum charge_type ctype,
25322546
static struct mem_cgroup *
25332547
__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
25342548
{
2549+
int i;
2550+
int count;
25352551
struct page_cgroup *pc;
25362552
struct mem_cgroup *mem = NULL;
25372553
int page_size = PAGE_SIZE;
@@ -2545,6 +2561,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
25452561
if (PageTransHuge(page))
25462562
page_size <<= compound_order(page);
25472563

2564+
count = page_size >> PAGE_SHIFT;
25482565
/*
25492566
* Check if our page_cgroup is valid
25502567
*/
@@ -2577,7 +2594,8 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
25772594
break;
25782595
}
25792596

2580-
mem_cgroup_charge_statistics(mem, pc, false);
2597+
for (i = 0; i < count; i++)
2598+
mem_cgroup_charge_statistics(mem, pc + i, false);
25812599

25822600
ClearPageCgroupUsed(pc);
25832601
/*

0 commit comments

Comments
 (0)