diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/fremap.c | 2 | ||||
-rw-r--r-- | mm/hugetlb.c | 39 | ||||
-rw-r--r-- | mm/mmap.c | 38 | ||||
-rw-r--r-- | mm/mprotect.c | 5 |
4 files changed, 51 insertions, 33 deletions
diff --git a/mm/fremap.c b/mm/fremap.c index 736ba7f3306a..b6ec85abbb39 100644 --- a/mm/fremap.c +++ b/mm/fremap.c | |||
@@ -198,7 +198,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, | |||
198 | flags &= MAP_NONBLOCK; | 198 | flags &= MAP_NONBLOCK; |
199 | get_file(file); | 199 | get_file(file); |
200 | addr = mmap_region(file, start, size, | 200 | addr = mmap_region(file, start, size, |
201 | flags, vma->vm_flags, pgoff, 1); | 201 | flags, vma->vm_flags, pgoff); |
202 | fput(file); | 202 | fput(file); |
203 | if (IS_ERR_VALUE(addr)) { | 203 | if (IS_ERR_VALUE(addr)) { |
204 | err = addr; | 204 | err = addr; |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 618e98304080..207464209546 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -2269,14 +2269,12 @@ 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 = 0, 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 | return 0; | ||
2279 | |||
2280 | /* | 2278 | /* |
2281 | * Shared mappings base their reservation on the number of pages that | 2279 | * Shared mappings base their reservation on the number of pages that |
2282 | * are already allocated on behalf of the file. Private mappings need | 2280 | * are already allocated on behalf of the file. Private mappings need |
@@ -2285,22 +2283,25 @@ int hugetlb_reserve_pages(struct inode *inode, | |||
2285 | */ | 2283 | */ |
2286 | if (!vma || vma->vm_flags & VM_SHARED) | 2284 | if (!vma || vma->vm_flags & VM_SHARED) |
2287 | chg = region_chg(&inode->i_mapping->private_list, from, to); | 2285 | chg = region_chg(&inode->i_mapping->private_list, from, to); |
2288 | else { | 2286 | else |
2289 | struct resv_map *resv_map = resv_map_alloc(); | ||
2290 | if (!resv_map) | ||
2291 | return -ENOMEM; | ||
2292 | |||
2293 | chg = to - from; | 2287 | chg = to - from; |
2294 | 2288 | ||
2295 | set_vma_resv_map(vma, resv_map); | ||
2296 | set_vma_resv_flags(vma, HPAGE_RESV_OWNER); | ||
2297 | } | ||
2298 | |||
2299 | if (chg < 0) | 2289 | if (chg < 0) |
2300 | return chg; | 2290 | return chg; |
2301 | 2291 | ||
2302 | if (hugetlb_get_quota(inode->i_mapping, chg)) | 2292 | if (hugetlb_get_quota(inode->i_mapping, chg)) |
2303 | return -ENOSPC; | 2293 | return -ENOSPC; |
2294 | |||
2295 | /* | ||
2296 | * Only apply hugepage reservation if asked. We still have to | ||
2297 | * take the filesystem quota because it is an upper limit | ||
2298 | * defined for the mount and not necessarily memory as a whole | ||
2299 | */ | ||
2300 | if (acctflag & VM_NORESERVE) { | ||
2301 | reset_vma_resv_huge_pages(vma); | ||
2302 | return 0; | ||
2303 | } | ||
2304 | |||
2304 | ret = hugetlb_acct_memory(h, chg); | 2305 | ret = hugetlb_acct_memory(h, chg); |
2305 | if (ret < 0) { | 2306 | if (ret < 0) { |
2306 | hugetlb_put_quota(inode->i_mapping, chg); | 2307 | hugetlb_put_quota(inode->i_mapping, chg); |
@@ -2308,6 +2309,16 @@ int hugetlb_reserve_pages(struct inode *inode, | |||
2308 | } | 2309 | } |
2309 | if (!vma || vma->vm_flags & VM_SHARED) | 2310 | if (!vma || vma->vm_flags & VM_SHARED) |
2310 | region_add(&inode->i_mapping->private_list, from, to); | 2311 | region_add(&inode->i_mapping->private_list, from, to); |
2312 | else { | ||
2313 | struct resv_map *resv_map = resv_map_alloc(); | ||
2314 | |||
2315 | if (!resv_map) | ||
2316 | return -ENOMEM; | ||
2317 | |||
2318 | set_vma_resv_map(vma, resv_map); | ||
2319 | set_vma_resv_flags(vma, HPAGE_RESV_OWNER); | ||
2320 | } | ||
2321 | |||
2311 | return 0; | 2322 | return 0; |
2312 | } | 2323 | } |
2313 | 2324 | ||
@@ -918,7 +918,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
918 | struct inode *inode; | 918 | struct inode *inode; |
919 | unsigned int vm_flags; | 919 | unsigned int vm_flags; |
920 | int error; | 920 | int error; |
921 | int accountable = 1; | ||
922 | unsigned long reqprot = prot; | 921 | unsigned long reqprot = prot; |
923 | 922 | ||
924 | /* | 923 | /* |
@@ -1019,8 +1018,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
1019 | return -EPERM; | 1018 | return -EPERM; |
1020 | vm_flags &= ~VM_MAYEXEC; | 1019 | vm_flags &= ~VM_MAYEXEC; |
1021 | } | 1020 | } |
1022 | if (is_file_hugepages(file)) | ||
1023 | accountable = 0; | ||
1024 | 1021 | ||
1025 | if (!file->f_op || !file->f_op->mmap) | 1022 | if (!file->f_op || !file->f_op->mmap) |
1026 | return -ENODEV; | 1023 | return -ENODEV; |
@@ -1053,8 +1050,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
1053 | if (error) | 1050 | if (error) |
1054 | return error; | 1051 | return error; |
1055 | 1052 | ||
1056 | return mmap_region(file, addr, len, flags, vm_flags, pgoff, | 1053 | return mmap_region(file, addr, len, flags, vm_flags, pgoff); |
1057 | accountable); | ||
1058 | } | 1054 | } |
1059 | EXPORT_SYMBOL(do_mmap_pgoff); | 1055 | EXPORT_SYMBOL(do_mmap_pgoff); |
1060 | 1056 | ||
@@ -1092,17 +1088,23 @@ int vma_wants_writenotify(struct vm_area_struct *vma) | |||
1092 | 1088 | ||
1093 | /* | 1089 | /* |
1094 | * We account for memory if it's a private writeable mapping, | 1090 | * We account for memory if it's a private writeable mapping, |
1095 | * and VM_NORESERVE wasn't set. | 1091 | * not hugepages and VM_NORESERVE wasn't set. |
1096 | */ | 1092 | */ |
1097 | static inline int accountable_mapping(unsigned int vm_flags) | 1093 | static inline int accountable_mapping(struct file *file, unsigned int vm_flags) |
1098 | { | 1094 | { |
1095 | /* | ||
1096 | * hugetlb has its own accounting separate from the core VM | ||
1097 | * VM_HUGETLB may not be set yet so we cannot check for that flag. | ||
1098 | */ | ||
1099 | if (file && is_file_hugepages(file)) | ||
1100 | return 0; | ||
1101 | |||
1099 | return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; | 1102 | return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; |
1100 | } | 1103 | } |
1101 | 1104 | ||
1102 | unsigned long mmap_region(struct file *file, unsigned long addr, | 1105 | unsigned long mmap_region(struct file *file, unsigned long addr, |
1103 | unsigned long len, unsigned long flags, | 1106 | unsigned long len, unsigned long flags, |
1104 | unsigned int vm_flags, unsigned long pgoff, | 1107 | unsigned int vm_flags, unsigned long pgoff) |
1105 | int accountable) | ||
1106 | { | 1108 | { |
1107 | struct mm_struct *mm = current->mm; | 1109 | struct mm_struct *mm = current->mm; |
1108 | struct vm_area_struct *vma, *prev; | 1110 | struct vm_area_struct *vma, *prev; |
@@ -1128,18 +1130,22 @@ munmap_back: | |||
1128 | 1130 | ||
1129 | /* | 1131 | /* |
1130 | * Set 'VM_NORESERVE' if we should not account for the | 1132 | * Set 'VM_NORESERVE' if we should not account for the |
1131 | * memory use of this mapping. We only honor MAP_NORESERVE | 1133 | * memory use of this mapping. |
1132 | * if we're allowed to overcommit memory. | ||
1133 | */ | 1134 | */ |
1134 | if ((flags & MAP_NORESERVE) && sysctl_overcommit_memory != OVERCOMMIT_NEVER) | 1135 | if ((flags & MAP_NORESERVE)) { |
1135 | vm_flags |= VM_NORESERVE; | 1136 | /* We honor MAP_NORESERVE if allowed to overcommit */ |
1136 | if (!accountable) | 1137 | if (sysctl_overcommit_memory != OVERCOMMIT_NEVER) |
1137 | vm_flags |= VM_NORESERVE; | 1138 | vm_flags |= VM_NORESERVE; |
1139 | |||
1140 | /* hugetlb applies strict overcommit unless MAP_NORESERVE */ | ||
1141 | if (file && is_file_hugepages(file)) | ||
1142 | vm_flags |= VM_NORESERVE; | ||
1143 | } | ||
1138 | 1144 | ||
1139 | /* | 1145 | /* |
1140 | * Private writable mapping: check memory availability | 1146 | * Private writable mapping: check memory availability |
1141 | */ | 1147 | */ |
1142 | if (accountable_mapping(vm_flags)) { | 1148 | if (accountable_mapping(file, vm_flags)) { |
1143 | charged = len >> PAGE_SHIFT; | 1149 | charged = len >> PAGE_SHIFT; |
1144 | if (security_vm_enough_memory(charged)) | 1150 | if (security_vm_enough_memory(charged)) |
1145 | return -ENOMEM; | 1151 | return -ENOMEM; |
diff --git a/mm/mprotect.c b/mm/mprotect.c index abe2694e13f4..258197b76fb4 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
@@ -151,10 +151,11 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, | |||
151 | /* | 151 | /* |
152 | * If we make a private mapping writable we increase our commit; | 152 | * If we make a private mapping writable we increase our commit; |
153 | * but (without finer accounting) cannot reduce our commit if we | 153 | * but (without finer accounting) cannot reduce our commit if we |
154 | * make it unwritable again. | 154 | * make it unwritable again. hugetlb mapping were accounted for |
155 | * even if read-only so there is no need to account for them here | ||
155 | */ | 156 | */ |
156 | if (newflags & VM_WRITE) { | 157 | if (newflags & VM_WRITE) { |
157 | if (!(oldflags & (VM_ACCOUNT|VM_WRITE| | 158 | if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_HUGETLB| |
158 | VM_SHARED|VM_NORESERVE))) { | 159 | VM_SHARED|VM_NORESERVE))) { |
159 | charged = nrpages; | 160 | charged = nrpages; |
160 | if (security_vm_enough_memory(charged)) | 161 | if (security_vm_enough_memory(charged)) |