aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/hugetlb.c123
1 files changed, 100 insertions, 23 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 4494976c2042..499cb72c74b1 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -96,36 +96,89 @@ void hugepage_put_subpool(struct hugepage_subpool *spool)
96 unlock_or_release_subpool(spool); 96 unlock_or_release_subpool(spool);
97} 97}
98 98
99static int hugepage_subpool_get_pages(struct hugepage_subpool *spool, 99/*
100 * Subpool accounting for allocating and reserving pages.
101 * Return -ENOMEM if there are not enough resources to satisfy the
102 * the request. Otherwise, return the number of pages by which the
103 * global pools must be adjusted (upward). The returned value may
104 * only be different than the passed value (delta) in the case where
105 * a subpool minimum size must be manitained.
106 */
107static long hugepage_subpool_get_pages(struct hugepage_subpool *spool,
100 long delta) 108 long delta)
101{ 109{
102 int ret = 0; 110 long ret = delta;
103 111
104 if (!spool) 112 if (!spool)
105 return 0; 113 return ret;
106 114
107 spin_lock(&spool->lock); 115 spin_lock(&spool->lock);
108 if ((spool->used_hpages + delta) <= spool->max_hpages) { 116
109 spool->used_hpages += delta; 117 if (spool->max_hpages != -1) { /* maximum size accounting */
110 } else { 118 if ((spool->used_hpages + delta) <= spool->max_hpages)
111 ret = -ENOMEM; 119 spool->used_hpages += delta;
120 else {
121 ret = -ENOMEM;
122 goto unlock_ret;
123 }
112 } 124 }
113 spin_unlock(&spool->lock);
114 125
126 if (spool->min_hpages != -1) { /* minimum size accounting */
127 if (delta > spool->rsv_hpages) {
128 /*
129 * Asking for more reserves than those already taken on
130 * behalf of subpool. Return difference.
131 */
132 ret = delta - spool->rsv_hpages;
133 spool->rsv_hpages = 0;
134 } else {
135 ret = 0; /* reserves already accounted for */
136 spool->rsv_hpages -= delta;
137 }
138 }
139
140unlock_ret:
141 spin_unlock(&spool->lock);
115 return ret; 142 return ret;
116} 143}
117 144
118static void hugepage_subpool_put_pages(struct hugepage_subpool *spool, 145/*
146 * Subpool accounting for freeing and unreserving pages.
147 * Return the number of global page reservations that must be dropped.
148 * The return value may only be different than the passed value (delta)
149 * in the case where a subpool minimum size must be maintained.
150 */
151static long hugepage_subpool_put_pages(struct hugepage_subpool *spool,
119 long delta) 152 long delta)
120{ 153{
154 long ret = delta;
155
121 if (!spool) 156 if (!spool)
122 return; 157 return delta;
123 158
124 spin_lock(&spool->lock); 159 spin_lock(&spool->lock);
125 spool->used_hpages -= delta; 160
126 /* If hugetlbfs_put_super couldn't free spool due to 161 if (spool->max_hpages != -1) /* maximum size accounting */
127 * an outstanding quota reference, free it now. */ 162 spool->used_hpages -= delta;
163
164 if (spool->min_hpages != -1) { /* minimum size accounting */
165 if (spool->rsv_hpages + delta <= spool->min_hpages)
166 ret = 0;
167 else
168 ret = spool->rsv_hpages + delta - spool->min_hpages;
169
170 spool->rsv_hpages += delta;
171 if (spool->rsv_hpages > spool->min_hpages)
172 spool->rsv_hpages = spool->min_hpages;
173 }
174
175 /*
176 * If hugetlbfs_put_super couldn't free spool due to an outstanding
177 * quota reference, free it now.
178 */
128 unlock_or_release_subpool(spool); 179 unlock_or_release_subpool(spool);
180
181 return ret;
129} 182}
130 183
131static inline struct hugepage_subpool *subpool_inode(struct inode *inode) 184static inline struct hugepage_subpool *subpool_inode(struct inode *inode)
@@ -873,6 +926,14 @@ void free_huge_page(struct page *page)
873 restore_reserve = PagePrivate(page); 926 restore_reserve = PagePrivate(page);
874 ClearPagePrivate(page); 927 ClearPagePrivate(page);
875 928
929 /*
930 * A return code of zero implies that the subpool will be under its
931 * minimum size if the reservation is not restored after page is free.
932 * Therefore, force restore_reserve operation.
933 */
934 if (hugepage_subpool_put_pages(spool, 1) == 0)
935 restore_reserve = true;
936
876 spin_lock(&hugetlb_lock); 937 spin_lock(&hugetlb_lock);
877 hugetlb_cgroup_uncharge_page(hstate_index(h), 938 hugetlb_cgroup_uncharge_page(hstate_index(h),
878 pages_per_huge_page(h), page); 939 pages_per_huge_page(h), page);
@@ -890,7 +951,6 @@ void free_huge_page(struct page *page)
890 enqueue_huge_page(h, page); 951 enqueue_huge_page(h, page);
891 } 952 }
892 spin_unlock(&hugetlb_lock); 953 spin_unlock(&hugetlb_lock);
893 hugepage_subpool_put_pages(spool, 1);
894} 954}
895 955
896static void prep_new_huge_page(struct hstate *h, struct page *page, int nid) 956static void prep_new_huge_page(struct hstate *h, struct page *page, int nid)
@@ -1385,7 +1445,7 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
1385 if (chg < 0) 1445 if (chg < 0)
1386 return ERR_PTR(-ENOMEM); 1446 return ERR_PTR(-ENOMEM);
1387 if (chg || avoid_reserve) 1447 if (chg || avoid_reserve)
1388 if (hugepage_subpool_get_pages(spool, 1)) 1448 if (hugepage_subpool_get_pages(spool, 1) < 0)
1389 return ERR_PTR(-ENOSPC); 1449 return ERR_PTR(-ENOSPC);
1390 1450
1391 ret = hugetlb_cgroup_charge_cgroup(idx, pages_per_huge_page(h), &h_cg); 1451 ret = hugetlb_cgroup_charge_cgroup(idx, pages_per_huge_page(h), &h_cg);
@@ -2453,6 +2513,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
2453 struct resv_map *resv = vma_resv_map(vma); 2513 struct resv_map *resv = vma_resv_map(vma);
2454 struct hugepage_subpool *spool = subpool_vma(vma); 2514 struct hugepage_subpool *spool = subpool_vma(vma);
2455 unsigned long reserve, start, end; 2515 unsigned long reserve, start, end;
2516 long gbl_reserve;
2456 2517
2457 if (!resv || !is_vma_resv_set(vma, HPAGE_RESV_OWNER)) 2518 if (!resv || !is_vma_resv_set(vma, HPAGE_RESV_OWNER))
2458 return; 2519 return;
@@ -2465,8 +2526,12 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
2465 kref_put(&resv->refs, resv_map_release); 2526 kref_put(&resv->refs, resv_map_release);
2466 2527
2467 if (reserve) { 2528 if (reserve) {
2468 hugetlb_acct_memory(h, -reserve); 2529 /*
2469 hugepage_subpool_put_pages(spool, reserve); 2530 * Decrement reserve counts. The global reserve count may be
2531 * adjusted if the subpool has a minimum size.
2532 */
2533 gbl_reserve = hugepage_subpool_put_pages(spool, reserve);
2534 hugetlb_acct_memory(h, -gbl_reserve);
2470 } 2535 }
2471} 2536}
2472 2537
@@ -3446,6 +3511,7 @@ int hugetlb_reserve_pages(struct inode *inode,
3446 struct hstate *h = hstate_inode(inode); 3511 struct hstate *h = hstate_inode(inode);
3447 struct hugepage_subpool *spool = subpool_inode(inode); 3512 struct hugepage_subpool *spool = subpool_inode(inode);
3448 struct resv_map *resv_map; 3513 struct resv_map *resv_map;
3514 long gbl_reserve;
3449 3515
3450 /* 3516 /*
3451 * Only apply hugepage reservation if asked. At fault time, an 3517 * Only apply hugepage reservation if asked. At fault time, an
@@ -3482,8 +3548,13 @@ int hugetlb_reserve_pages(struct inode *inode,
3482 goto out_err; 3548 goto out_err;
3483 } 3549 }
3484 3550
3485 /* There must be enough pages in the subpool for the mapping */ 3551 /*
3486 if (hugepage_subpool_get_pages(spool, chg)) { 3552 * There must be enough pages in the subpool for the mapping. If
3553 * the subpool has a minimum size, there may be some global
3554 * reservations already in place (gbl_reserve).
3555 */
3556 gbl_reserve = hugepage_subpool_get_pages(spool, chg);
3557 if (gbl_reserve < 0) {
3487 ret = -ENOSPC; 3558 ret = -ENOSPC;
3488 goto out_err; 3559 goto out_err;
3489 } 3560 }
@@ -3492,9 +3563,10 @@ int hugetlb_reserve_pages(struct inode *inode,
3492 * Check enough hugepages are available for the reservation. 3563 * Check enough hugepages are available for the reservation.
3493 * Hand the pages back to the subpool if there are not 3564 * Hand the pages back to the subpool if there are not
3494 */ 3565 */
3495 ret = hugetlb_acct_memory(h, chg); 3566 ret = hugetlb_acct_memory(h, gbl_reserve);
3496 if (ret < 0) { 3567 if (ret < 0) {
3497 hugepage_subpool_put_pages(spool, chg); 3568 /* put back original number of pages, chg */
3569 (void)hugepage_subpool_put_pages(spool, chg);
3498 goto out_err; 3570 goto out_err;
3499 } 3571 }
3500 3572
@@ -3524,6 +3596,7 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
3524 struct resv_map *resv_map = inode_resv_map(inode); 3596 struct resv_map *resv_map = inode_resv_map(inode);
3525 long chg = 0; 3597 long chg = 0;
3526 struct hugepage_subpool *spool = subpool_inode(inode); 3598 struct hugepage_subpool *spool = subpool_inode(inode);
3599 long gbl_reserve;
3527 3600
3528 if (resv_map) 3601 if (resv_map)
3529 chg = region_truncate(resv_map, offset); 3602 chg = region_truncate(resv_map, offset);
@@ -3531,8 +3604,12 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
3531 inode->i_blocks -= (blocks_per_huge_page(h) * freed); 3604 inode->i_blocks -= (blocks_per_huge_page(h) * freed);
3532 spin_unlock(&inode->i_lock); 3605 spin_unlock(&inode->i_lock);
3533 3606
3534 hugepage_subpool_put_pages(spool, (chg - freed)); 3607 /*
3535 hugetlb_acct_memory(h, -(chg - freed)); 3608 * If the subpool has a minimum size, the number of global
3609 * reservations to be released may be adjusted.
3610 */
3611 gbl_reserve = hugepage_subpool_put_pages(spool, (chg - freed));
3612 hugetlb_acct_memory(h, -gbl_reserve);
3536} 3613}
3537 3614
3538#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE 3615#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE