aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2009-04-30 18:08:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-05-02 18:36:09 -0400
commitbc43f75cd9815833b27831600ccade672edb5e43 (patch)
tree87ded2ff291b63259ac3df846a09d8348174f636 /mm/memory.c
parent53951bd57dfe2da58f86cdf276719082d80d8485 (diff)
mm: fix pageref leak in do_swap_page()
By the time the memory cgroup code is notified about a swapin we already hold a reference on the fault page. If the cgroup callback fails make sure to unlock AND release the page reference which was taken by lookup_swap_cach(), or we leak the reference. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Reviewed-by: Minchan Kim <minchan.kim@gmail.com> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c
index cf6873e91c6a..6a4ef0fd0711 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2458,8 +2458,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
2458 2458
2459 if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { 2459 if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) {
2460 ret = VM_FAULT_OOM; 2460 ret = VM_FAULT_OOM;
2461 unlock_page(page); 2461 goto out_page;
2462 goto out;
2463 } 2462 }
2464 2463
2465 /* 2464 /*
@@ -2521,6 +2520,7 @@ out:
2521out_nomap: 2520out_nomap:
2522 mem_cgroup_cancel_charge_swapin(ptr); 2521 mem_cgroup_cancel_charge_swapin(ptr);
2523 pte_unmap_unlock(page_table, ptl); 2522 pte_unmap_unlock(page_table, ptl);
2523out_page:
2524 unlock_page(page); 2524 unlock_page(page);
2525 page_cache_release(page); 2525 page_cache_release(page);
2526 return ret; 2526 return ret;