summary refs log tree commit diff
path: root/mm/memory.c
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2009-04-30 15:08:08 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-05-02 15:36:09 -0700
commitbc43f75cd9815833b27831600ccade672edb5e43 (patch)
tree87ded2ff291b63259ac3df846a09d8348174f636 /mm/memory.c
parent53951bd57dfe2da58f86cdf276719082d80d8485 (diff)
downloadlinux-bc43f75cd9815833b27831600ccade672edb5e43.tar.gz
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,
 
 	if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) {
 		ret = VM_FAULT_OOM;
-		unlock_page(page);
-		goto out;
+		goto out_page;
 	}
 
 	/*
@@ -2521,6 +2520,7 @@ out:
 out_nomap:
 	mem_cgroup_cancel_charge_swapin(ptr);
 	pte_unmap_unlock(page_table, ptl);
+out_page:
 	unlock_page(page);
 	page_cache_release(page);
 	return ret;