aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2011-03-23 19:42:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-23 22:46:27 -0400
commit5564e88ba6fd2f6dcd83a592771810cd84b5ae80 (patch)
treee2b3a0835067825308a254c7531c891d4d69e701 /mm
parentde3638d9cdc89ac899225996b8dcedbcbc53bdd2 (diff)
memcg: condense page_cgroup-to-page lookup points
The per-cgroup LRU lists string up 'struct page_cgroup's. To get from those structures to the page they represent, a lookup is required. Currently, the lookup is done through a direct pointer in struct page_cgroup, so a lot of functions down the callchain do this lookup by themselves instead of receiving the page pointer from their callers. The next patch removes this pointer, however, and the lookup is no longer that straight-forward. In preparation for that, this patch only leaves the non-optional lookups when coming directly from the LRU list and passes the page down the stack. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-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: Minchan Kim <minchan.kim@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/memcontrol.c38
1 files changed, 23 insertions, 15 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e9d33dc151a5..e286e1603e4f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1077,9 +1077,11 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
1077 if (scan >= nr_to_scan) 1077 if (scan >= nr_to_scan)
1078 break; 1078 break;
1079 1079
1080 page = pc->page;
1081 if (unlikely(!PageCgroupUsed(pc))) 1080 if (unlikely(!PageCgroupUsed(pc)))
1082 continue; 1081 continue;
1082
1083 page = pc->page;
1084
1083 if (unlikely(!PageLRU(page))) 1085 if (unlikely(!PageLRU(page)))
1084 continue; 1086 continue;
1085 1087
@@ -2108,6 +2110,7 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
2108} 2110}
2109 2111
2110static void __mem_cgroup_commit_charge(struct mem_cgroup *mem, 2112static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
2113 struct page *page,
2111 struct page_cgroup *pc, 2114 struct page_cgroup *pc,
2112 enum charge_type ctype, 2115 enum charge_type ctype,
2113 int page_size) 2116 int page_size)
@@ -2154,7 +2157,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
2154 * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree. 2157 * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree.
2155 * if they exceeds softlimit. 2158 * if they exceeds softlimit.
2156 */ 2159 */
2157 memcg_check_events(mem, pc->page); 2160 memcg_check_events(mem, page);
2158} 2161}
2159 2162
2160#ifdef CONFIG_TRANSPARENT_HUGEPAGE 2163#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -2201,6 +2204,7 @@ void mem_cgroup_split_huge_fixup(struct page *head, struct page *tail)
2201 2204
2202/** 2205/**
2203 * mem_cgroup_move_account - move account of the page 2206 * mem_cgroup_move_account - move account of the page
2207 * @page: the page
2204 * @pc: page_cgroup of the page. 2208 * @pc: page_cgroup of the page.
2205 * @from: mem_cgroup which the page is moved from. 2209 * @from: mem_cgroup which the page is moved from.
2206 * @to: mem_cgroup which the page is moved to. @from != @to. 2210 * @to: mem_cgroup which the page is moved to. @from != @to.
@@ -2216,7 +2220,7 @@ void mem_cgroup_split_huge_fixup(struct page *head, struct page *tail)
2216 * true, this function does "uncharge" from old cgroup, but it doesn't if 2220 * true, this function does "uncharge" from old cgroup, but it doesn't if
2217 * @uncharge is false, so a caller should do "uncharge". 2221 * @uncharge is false, so a caller should do "uncharge".
2218 */ 2222 */
2219static int mem_cgroup_move_account(struct page_cgroup *pc, 2223static int mem_cgroup_move_account(struct page *page, struct page_cgroup *pc,
2220 struct mem_cgroup *from, struct mem_cgroup *to, 2224 struct mem_cgroup *from, struct mem_cgroup *to,
2221 bool uncharge, int charge_size) 2225 bool uncharge, int charge_size)
2222{ 2226{
@@ -2225,7 +2229,7 @@ static int mem_cgroup_move_account(struct page_cgroup *pc,
2225 int ret; 2229 int ret;
2226 2230
2227 VM_BUG_ON(from == to); 2231 VM_BUG_ON(from == to);
2228 VM_BUG_ON(PageLRU(pc->page)); 2232 VM_BUG_ON(PageLRU(page));
2229 /* 2233 /*
2230 * The page is isolated from LRU. So, collapse function 2234 * The page is isolated from LRU. So, collapse function
2231 * will not handle this page. But page splitting can happen. 2235 * will not handle this page. But page splitting can happen.
@@ -2233,7 +2237,7 @@ static int mem_cgroup_move_account(struct page_cgroup *pc,
2233 * hold it. 2237 * hold it.
2234 */ 2238 */
2235 ret = -EBUSY; 2239 ret = -EBUSY;
2236 if (charge_size > PAGE_SIZE && !PageTransHuge(pc->page)) 2240 if (charge_size > PAGE_SIZE && !PageTransHuge(page))
2237 goto out; 2241 goto out;
2238 2242
2239 lock_page_cgroup(pc); 2243 lock_page_cgroup(pc);
@@ -2273,8 +2277,8 @@ unlock:
2273 /* 2277 /*
2274 * check events 2278 * check events
2275 */ 2279 */
2276 memcg_check_events(to, pc->page); 2280 memcg_check_events(to, page);
2277 memcg_check_events(from, pc->page); 2281 memcg_check_events(from, page);
2278out: 2282out:
2279 return ret; 2283 return ret;
2280} 2284}
@@ -2283,11 +2287,11 @@ out:
2283 * move charges to its parent. 2287 * move charges to its parent.
2284 */ 2288 */
2285 2289
2286static int mem_cgroup_move_parent(struct page_cgroup *pc, 2290static int mem_cgroup_move_parent(struct page *page,
2291 struct page_cgroup *pc,
2287 struct mem_cgroup *child, 2292 struct mem_cgroup *child,
2288 gfp_t gfp_mask) 2293 gfp_t gfp_mask)
2289{ 2294{
2290 struct page *page = pc->page;
2291 struct cgroup *cg = child->css.cgroup; 2295 struct cgroup *cg = child->css.cgroup;
2292 struct cgroup *pcg = cg->parent; 2296 struct cgroup *pcg = cg->parent;
2293 struct mem_cgroup *parent; 2297 struct mem_cgroup *parent;
@@ -2317,7 +2321,7 @@ static int mem_cgroup_move_parent(struct page_cgroup *pc,
2317 if (page_size > PAGE_SIZE) 2321 if (page_size > PAGE_SIZE)
2318 flags = compound_lock_irqsave(page); 2322 flags = compound_lock_irqsave(page);
2319 2323
2320 ret = mem_cgroup_move_account(pc, child, parent, true, page_size); 2324 ret = mem_cgroup_move_account(page, pc, child, parent, true, page_size);
2321 if (ret) 2325 if (ret)
2322 mem_cgroup_cancel_charge(parent, page_size); 2326 mem_cgroup_cancel_charge(parent, page_size);
2323 2327
@@ -2363,7 +2367,7 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
2363 if (ret || !mem) 2367 if (ret || !mem)
2364 return ret; 2368 return ret;
2365 2369
2366 __mem_cgroup_commit_charge(mem, pc, ctype, page_size); 2370 __mem_cgroup_commit_charge(mem, page, pc, ctype, page_size);
2367 return 0; 2371 return 0;
2368} 2372}
2369 2373
@@ -2501,7 +2505,7 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
2501 cgroup_exclude_rmdir(&ptr->css); 2505 cgroup_exclude_rmdir(&ptr->css);
2502 pc = lookup_page_cgroup(page); 2506 pc = lookup_page_cgroup(page);
2503 mem_cgroup_lru_del_before_commit_swapcache(page); 2507 mem_cgroup_lru_del_before_commit_swapcache(page);
2504 __mem_cgroup_commit_charge(ptr, pc, ctype, PAGE_SIZE); 2508 __mem_cgroup_commit_charge(ptr, page, pc, ctype, PAGE_SIZE);
2505 mem_cgroup_lru_add_after_commit_swapcache(page); 2509 mem_cgroup_lru_add_after_commit_swapcache(page);
2506 /* 2510 /*
2507 * Now swap is on-memory. This means this page may be 2511 * Now swap is on-memory. This means this page may be
@@ -2956,7 +2960,7 @@ int mem_cgroup_prepare_migration(struct page *page,
2956 ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; 2960 ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
2957 else 2961 else
2958 ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM; 2962 ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
2959 __mem_cgroup_commit_charge(mem, pc, ctype, PAGE_SIZE); 2963 __mem_cgroup_commit_charge(mem, page, pc, ctype, PAGE_SIZE);
2960 return ret; 2964 return ret;
2961} 2965}
2962 2966
@@ -3323,6 +3327,8 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
3323 loop += 256; 3327 loop += 256;
3324 busy = NULL; 3328 busy = NULL;
3325 while (loop--) { 3329 while (loop--) {
3330 struct page *page;
3331
3326 ret = 0; 3332 ret = 0;
3327 spin_lock_irqsave(&zone->lru_lock, flags); 3333 spin_lock_irqsave(&zone->lru_lock, flags);
3328 if (list_empty(list)) { 3334 if (list_empty(list)) {
@@ -3338,7 +3344,9 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
3338 } 3344 }
3339 spin_unlock_irqrestore(&zone->lru_lock, flags); 3345 spin_unlock_irqrestore(&zone->lru_lock, flags);
3340 3346
3341 ret = mem_cgroup_move_parent(pc, mem, GFP_KERNEL); 3347 page = pc->page;
3348
3349 ret = mem_cgroup_move_parent(page, pc, mem, GFP_KERNEL);
3342 if (ret == -ENOMEM) 3350 if (ret == -ENOMEM)
3343 break; 3351 break;
3344 3352
@@ -4956,7 +4964,7 @@ retry:
4956 if (isolate_lru_page(page)) 4964 if (isolate_lru_page(page))
4957 goto put; 4965 goto put;
4958 pc = lookup_page_cgroup(page); 4966 pc = lookup_page_cgroup(page);
4959 if (!mem_cgroup_move_account(pc, 4967 if (!mem_cgroup_move_account(page, pc,
4960 mc.from, mc.to, false, PAGE_SIZE)) { 4968 mc.from, mc.to, false, PAGE_SIZE)) {
4961 mc.precharge--; 4969 mc.precharge--;
4962 /* we uncharge from mc.from later. */ 4970 /* we uncharge from mc.from later. */