aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2008-02-07 03:14:22 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 11:42:20 -0500
commit82369553d6d3bc67c54129a02e0bc0b5b88f3045 (patch)
tree1d80a6cc9f5840550ad025b32ac8ef8fd915fd98 /mm/memcontrol.c
parent3be91277e754c7db04eae145ba622b3a3e3ad96d (diff)
memcgroup: fix hang with shmem/tmpfs
The memcgroup regime relies upon a cgroup reclaiming pages from itself within add_to_page_cache: which may involve some waiting. Whereas shmem and tmpfs rely upon using add_to_page_cache while holding a spinlock: when it cannot wait. The consequence is that when a cgroup reaches its limit, shmem_getpage just hangs - unless there is outside memory pressure too, neither kswapd nor radix_tree_preload get it out of the retry loop. In most cases we can mem_cgroup_cache_charge the page waitably first, to attach the page_cgroup in advance, so add_to_page_cache will do no more than increment a count; then mem_cgroup_uncharge_page after (in both success and failure cases) to balance the books again. And where there used to be a congestion_wait for kswapd (recently made redundant by radix_tree_preload), use mem_cgroup_cache_charge with NULL page to go through a cycle of allocation and freeing, without accounting to any particular page, and without updating the statistics vector. This brings the cgroup below its limit so the next try usually succeeds. Signed-off-by: Hugh Dickins <hugh@veritas.com> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Mel Gorman <mel@csn.ul.ie> 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.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index dbf571547c0..11b23f203d6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -329,23 +329,26 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
329 * with it 329 * with it
330 */ 330 */
331retry: 331retry:
332 lock_page_cgroup(page); 332 if (page) {
333 pc = page_get_page_cgroup(page); 333 lock_page_cgroup(page);
334 /* 334 pc = page_get_page_cgroup(page);
335 * The page_cgroup exists and the page has already been accounted 335 /*
336 */ 336 * The page_cgroup exists and
337 if (pc) { 337 * the page has already been accounted.
338 if (unlikely(!atomic_inc_not_zero(&pc->ref_cnt))) { 338 */
339 /* this page is under being uncharged ? */ 339 if (pc) {
340 unlock_page_cgroup(page); 340 if (unlikely(!atomic_inc_not_zero(&pc->ref_cnt))) {
341 cpu_relax(); 341 /* this page is under being uncharged ? */
342 goto retry; 342 unlock_page_cgroup(page);
343 } else { 343 cpu_relax();
344 unlock_page_cgroup(page); 344 goto retry;
345 goto done; 345 } else {
346 unlock_page_cgroup(page);
347 goto done;
348 }
346 } 349 }
350 unlock_page_cgroup(page);
347 } 351 }
348 unlock_page_cgroup(page);
349 352
350 pc = kzalloc(sizeof(struct page_cgroup), gfp_mask); 353 pc = kzalloc(sizeof(struct page_cgroup), gfp_mask);
351 if (pc == NULL) 354 if (pc == NULL)
@@ -404,7 +407,7 @@ retry:
404 if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) 407 if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE)
405 pc->flags |= PAGE_CGROUP_FLAG_CACHE; 408 pc->flags |= PAGE_CGROUP_FLAG_CACHE;
406 409
407 if (page_cgroup_assign_new_page_cgroup(page, pc)) { 410 if (!page || page_cgroup_assign_new_page_cgroup(page, pc)) {
408 /* 411 /*
409 * Another charge has been added to this page already. 412 * Another charge has been added to this page already.
410 * We take lock_page_cgroup(page) again and read 413 * We take lock_page_cgroup(page) again and read
@@ -413,6 +416,8 @@ retry:
413 res_counter_uncharge(&mem->res, PAGE_SIZE); 416 res_counter_uncharge(&mem->res, PAGE_SIZE);
414 css_put(&mem->css); 417 css_put(&mem->css);
415 kfree(pc); 418 kfree(pc);
419 if (!page)
420 goto done;
416 goto retry; 421 goto retry;
417 } 422 }
418 423