diff options
Diffstat (limited to 'mm/hugetlb.c')
| -rw-r--r-- | mm/hugetlb.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 618e98304080..107da3d809a8 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
| @@ -2269,12 +2269,18 @@ void hugetlb_change_protection(struct vm_area_struct *vma, | |||
| 2269 | 2269 | ||
| 2270 | int hugetlb_reserve_pages(struct inode *inode, | 2270 | int hugetlb_reserve_pages(struct inode *inode, |
| 2271 | long from, long to, | 2271 | long from, long to, |
| 2272 | struct vm_area_struct *vma) | 2272 | struct vm_area_struct *vma, |
| 2273 | int acctflag) | ||
| 2273 | { | 2274 | { |
| 2274 | long ret, chg; | 2275 | long ret, chg; |
| 2275 | struct hstate *h = hstate_inode(inode); | 2276 | struct hstate *h = hstate_inode(inode); |
| 2276 | 2277 | ||
| 2277 | if (vma && vma->vm_flags & VM_NORESERVE) | 2278 | /* |
| 2279 | * Only apply hugepage reservation if asked. At fault time, an | ||
| 2280 | * attempt will be made for VM_NORESERVE to allocate a page | ||
| 2281 | * and filesystem quota without using reserves | ||
| 2282 | */ | ||
| 2283 | if (acctflag & VM_NORESERVE) | ||
| 2278 | return 0; | 2284 | return 0; |
| 2279 | 2285 | ||
| 2280 | /* | 2286 | /* |
| @@ -2299,13 +2305,31 @@ int hugetlb_reserve_pages(struct inode *inode, | |||
| 2299 | if (chg < 0) | 2305 | if (chg < 0) |
| 2300 | return chg; | 2306 | return chg; |
| 2301 | 2307 | ||
| 2308 | /* There must be enough filesystem quota for the mapping */ | ||
| 2302 | if (hugetlb_get_quota(inode->i_mapping, chg)) | 2309 | if (hugetlb_get_quota(inode->i_mapping, chg)) |
| 2303 | return -ENOSPC; | 2310 | return -ENOSPC; |
| 2311 | |||
| 2312 | /* | ||
| 2313 | * Check enough hugepages are available for the reservation. | ||
| 2314 | * Hand back the quota if there are not | ||
| 2315 | */ | ||
| 2304 | ret = hugetlb_acct_memory(h, chg); | 2316 | ret = hugetlb_acct_memory(h, chg); |
| 2305 | if (ret < 0) { | 2317 | if (ret < 0) { |
| 2306 | hugetlb_put_quota(inode->i_mapping, chg); | 2318 | hugetlb_put_quota(inode->i_mapping, chg); |
| 2307 | return ret; | 2319 | return ret; |
| 2308 | } | 2320 | } |
| 2321 | |||
| 2322 | /* | ||
| 2323 | * Account for the reservations made. Shared mappings record regions | ||
| 2324 | * that have reservations as they are shared by multiple VMAs. | ||
| 2325 | * When the last VMA disappears, the region map says how much | ||
| 2326 | * the reservation was and the page cache tells how much of | ||
| 2327 | * the reservation was consumed. Private mappings are per-VMA and | ||
| 2328 | * only the consumed reservations are tracked. When the VMA | ||
| 2329 | * disappears, the original reservation is the VMA size and the | ||
| 2330 | * consumed reservations are stored in the map. Hence, nothing | ||
| 2331 | * else has to be done for private mappings here | ||
| 2332 | */ | ||
| 2309 | if (!vma || vma->vm_flags & VM_SHARED) | 2333 | if (!vma || vma->vm_flags & VM_SHARED) |
| 2310 | region_add(&inode->i_mapping->private_list, from, to); | 2334 | region_add(&inode->i_mapping->private_list, from, to); |
| 2311 | return 0; | 2335 | return 0; |
