diff options
-rw-r--r-- | mm/hugetlb.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 1e317465ecd1..b52b6ddd6c15 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -367,7 +367,7 @@ static struct page *alloc_huge_page_shared(struct vm_area_struct *vma, | |||
367 | spin_lock(&hugetlb_lock); | 367 | spin_lock(&hugetlb_lock); |
368 | page = dequeue_huge_page(vma, addr); | 368 | page = dequeue_huge_page(vma, addr); |
369 | spin_unlock(&hugetlb_lock); | 369 | spin_unlock(&hugetlb_lock); |
370 | return page; | 370 | return page ? page : ERR_PTR(-VM_FAULT_OOM); |
371 | } | 371 | } |
372 | 372 | ||
373 | static struct page *alloc_huge_page_private(struct vm_area_struct *vma, | 373 | static struct page *alloc_huge_page_private(struct vm_area_struct *vma, |
@@ -375,13 +375,16 @@ static struct page *alloc_huge_page_private(struct vm_area_struct *vma, | |||
375 | { | 375 | { |
376 | struct page *page = NULL; | 376 | struct page *page = NULL; |
377 | 377 | ||
378 | if (hugetlb_get_quota(vma->vm_file->f_mapping, 1)) | ||
379 | return ERR_PTR(-VM_FAULT_SIGBUS); | ||
380 | |||
378 | spin_lock(&hugetlb_lock); | 381 | spin_lock(&hugetlb_lock); |
379 | if (free_huge_pages > resv_huge_pages) | 382 | if (free_huge_pages > resv_huge_pages) |
380 | page = dequeue_huge_page(vma, addr); | 383 | page = dequeue_huge_page(vma, addr); |
381 | spin_unlock(&hugetlb_lock); | 384 | spin_unlock(&hugetlb_lock); |
382 | if (!page) | 385 | if (!page) |
383 | page = alloc_buddy_huge_page(vma, addr); | 386 | page = alloc_buddy_huge_page(vma, addr); |
384 | return page; | 387 | return page ? page : ERR_PTR(-VM_FAULT_OOM); |
385 | } | 388 | } |
386 | 389 | ||
387 | static struct page *alloc_huge_page(struct vm_area_struct *vma, | 390 | static struct page *alloc_huge_page(struct vm_area_struct *vma, |
@@ -390,19 +393,16 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, | |||
390 | struct page *page; | 393 | struct page *page; |
391 | struct address_space *mapping = vma->vm_file->f_mapping; | 394 | struct address_space *mapping = vma->vm_file->f_mapping; |
392 | 395 | ||
393 | if (hugetlb_get_quota(mapping, 1)) | ||
394 | return ERR_PTR(-VM_FAULT_SIGBUS); | ||
395 | |||
396 | if (vma->vm_flags & VM_MAYSHARE) | 396 | if (vma->vm_flags & VM_MAYSHARE) |
397 | page = alloc_huge_page_shared(vma, addr); | 397 | page = alloc_huge_page_shared(vma, addr); |
398 | else | 398 | else |
399 | page = alloc_huge_page_private(vma, addr); | 399 | page = alloc_huge_page_private(vma, addr); |
400 | if (page) { | 400 | |
401 | if (!IS_ERR(page)) { | ||
401 | set_page_refcounted(page); | 402 | set_page_refcounted(page); |
402 | set_page_private(page, (unsigned long) mapping); | 403 | set_page_private(page, (unsigned long) mapping); |
403 | return page; | 404 | } |
404 | } else | 405 | return page; |
405 | return ERR_PTR(-VM_FAULT_OOM); | ||
406 | } | 406 | } |
407 | 407 | ||
408 | static int __init hugetlb_init(void) | 408 | static int __init hugetlb_init(void) |
@@ -1148,6 +1148,8 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to) | |||
1148 | if (chg < 0) | 1148 | if (chg < 0) |
1149 | return chg; | 1149 | return chg; |
1150 | 1150 | ||
1151 | if (hugetlb_get_quota(inode->i_mapping, chg)) | ||
1152 | return -ENOSPC; | ||
1151 | ret = hugetlb_acct_memory(chg); | 1153 | ret = hugetlb_acct_memory(chg); |
1152 | if (ret < 0) | 1154 | if (ret < 0) |
1153 | return ret; | 1155 | return ret; |
@@ -1158,5 +1160,6 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to) | |||
1158 | void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) | 1160 | void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) |
1159 | { | 1161 | { |
1160 | long chg = region_truncate(&inode->i_mapping->private_list, offset); | 1162 | long chg = region_truncate(&inode->i_mapping->private_list, offset); |
1161 | hugetlb_acct_memory(freed - chg); | 1163 | hugetlb_put_quota(inode->i_mapping, (chg - freed)); |
1164 | hugetlb_acct_memory(-(chg - freed)); | ||
1162 | } | 1165 | } |