diff options
author | Johannes Weiner <hannes@cmpxchg.org> | 2009-04-30 18:08:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-05-02 18:36:09 -0400 |
commit | bc43f75cd9815833b27831600ccade672edb5e43 (patch) | |
tree | 87ded2ff291b63259ac3df846a09d8348174f636 /mm | |
parent | 53951bd57dfe2da58f86cdf276719082d80d8485 (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')
-rw-r--r-- | mm/memory.c | 4 |
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: | |||
2521 | out_nomap: | 2520 | out_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); |
2523 | out_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; |