From 06b22790e3a86b948715803f599be81f5476adc0 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 7 Feb 2008 00:14:19 -0800 Subject: [PATCH] --- yaml --- r: 83785 b: refs/heads/master c: 3be91277e754c7db04eae145ba622b3a3e3ad96d h: refs/heads/master i: 83783: e951088ce21e40ebc2364f71713612b3656c701a v: v3 --- [refs] | 2 +- trunk/mm/memcontrol.c | 44 +++++++++++++++---------------------------- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/[refs] b/[refs] index dd298c6c90d0..426d3a955b2e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ac44d354d5c9ced49b1165d6496f134501134219 +refs/heads/master: 3be91277e754c7db04eae145ba622b3a3e3ad96d diff --git a/trunk/mm/memcontrol.c b/trunk/mm/memcontrol.c index 160101a05b4d..dbf571547c03 100644 --- a/trunk/mm/memcontrol.c +++ b/trunk/mm/memcontrol.c @@ -345,23 +345,22 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, goto done; } } - unlock_page_cgroup(page); pc = kzalloc(sizeof(struct page_cgroup), gfp_mask); if (pc == NULL) goto err; - rcu_read_lock(); /* - * We always charge the cgroup the mm_struct belongs to - * the mm_struct's mem_cgroup changes on task migration if the + * We always charge the cgroup the mm_struct belongs to. + * The mm_struct's mem_cgroup changes on task migration if the * thread group leader migrates. It's possible that mm is not * set, if so charge the init_mm (happens for pagecache usage). */ if (!mm) mm = &init_mm; + rcu_read_lock(); mem = rcu_dereference(mm->mem_cgroup); /* * For every charge from the cgroup, increment reference @@ -375,12 +374,8 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, * the cgroup limit. */ while (res_counter_charge(&mem->res, PAGE_SIZE)) { - bool is_atomic = gfp_mask & GFP_ATOMIC; - /* - * We cannot reclaim under GFP_ATOMIC, fail the charge - */ - if (is_atomic) - goto noreclaim; + if (!(gfp_mask & __GFP_WAIT)) + goto out; if (try_to_free_mem_cgroup_pages(mem, gfp_mask)) continue; @@ -394,23 +389,12 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, */ if (res_counter_check_under_limit(&mem->res)) continue; - /* - * Since we control both RSS and cache, we end up with a - * very interesting scenario where we end up reclaiming - * memory (essentially RSS), since the memory is pushed - * to swap cache, we eventually end up adding those - * pages back to our list. Hence we give ourselves a - * few chances before we fail - */ - else if (nr_retries--) { - congestion_wait(WRITE, HZ/10); - continue; + + if (!nr_retries--) { + mem_cgroup_out_of_memory(mem, gfp_mask); + goto out; } -noreclaim: - css_put(&mem->css); - if (!is_atomic) - mem_cgroup_out_of_memory(mem, GFP_KERNEL); - goto free_pc; + congestion_wait(WRITE, HZ/10); } atomic_set(&pc->ref_cnt, 1); @@ -419,10 +403,11 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, pc->flags = 0; if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) pc->flags |= PAGE_CGROUP_FLAG_CACHE; + if (page_cgroup_assign_new_page_cgroup(page, pc)) { /* - * an another charge is added to this page already. - * we do take lock_page_cgroup(page) again and read + * Another charge has been added to this page already. + * We take lock_page_cgroup(page) again and read * page->cgroup, increment refcnt.... just retry is OK. */ res_counter_uncharge(&mem->res, PAGE_SIZE); @@ -437,7 +422,8 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, done: return 0; -free_pc: +out: + css_put(&mem->css); kfree(pc); err: return -ENOMEM;