diff options
author | Ken Chen <kenchen@google.com> | 2008-01-14 03:55:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-01-14 11:52:23 -0500 |
commit | 68842c9b94560e647e8e7cc75cbb3dbe59f6fcb5 (patch) | |
tree | 58220ff2840a62155d3e7f934bc39e4cea673b39 /mm | |
parent | 747d016e7e25e216b31022fe2b012508d99fb682 (diff) |
hugetlbfs: fix quota leak
In the error path of both shared and private hugetlb page allocation,
the file system quota is never undone, leading to fs quota leak. Fix
them up.
[akpm@linux-foundation.org: cleanup, micro-optimise]
Signed-off-by: Ken Chen <kenchen@google.com>
Acked-by: Adam Litke <agl@us.ibm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: William Lee Irwin III <wli@holomorphy.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/hugetlb.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 7224a4f07106..e0fda156f021 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -418,9 +418,14 @@ static struct page *alloc_huge_page_private(struct vm_area_struct *vma, | |||
418 | if (free_huge_pages > resv_huge_pages) | 418 | if (free_huge_pages > resv_huge_pages) |
419 | page = dequeue_huge_page(vma, addr); | 419 | page = dequeue_huge_page(vma, addr); |
420 | spin_unlock(&hugetlb_lock); | 420 | spin_unlock(&hugetlb_lock); |
421 | if (!page) | 421 | if (!page) { |
422 | page = alloc_buddy_huge_page(vma, addr); | 422 | page = alloc_buddy_huge_page(vma, addr); |
423 | return page ? page : ERR_PTR(-VM_FAULT_OOM); | 423 | if (!page) { |
424 | hugetlb_put_quota(vma->vm_file->f_mapping, 1); | ||
425 | return ERR_PTR(-VM_FAULT_OOM); | ||
426 | } | ||
427 | } | ||
428 | return page; | ||
424 | } | 429 | } |
425 | 430 | ||
426 | static struct page *alloc_huge_page(struct vm_area_struct *vma, | 431 | static struct page *alloc_huge_page(struct vm_area_struct *vma, |
@@ -1206,8 +1211,10 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to) | |||
1206 | if (hugetlb_get_quota(inode->i_mapping, chg)) | 1211 | if (hugetlb_get_quota(inode->i_mapping, chg)) |
1207 | return -ENOSPC; | 1212 | return -ENOSPC; |
1208 | ret = hugetlb_acct_memory(chg); | 1213 | ret = hugetlb_acct_memory(chg); |
1209 | if (ret < 0) | 1214 | if (ret < 0) { |
1215 | hugetlb_put_quota(inode->i_mapping, chg); | ||
1210 | return ret; | 1216 | return ret; |
1217 | } | ||
1211 | region_add(&inode->i_mapping->private_list, from, to); | 1218 | region_add(&inode->i_mapping->private_list, from, to); |
1212 | return 0; | 1219 | return 0; |
1213 | } | 1220 | } |