diff options
Diffstat (limited to 'mm/mmap.c')
-rw-r--r-- | mm/mmap.c | 48 |
1 files changed, 28 insertions, 20 deletions
@@ -919,7 +919,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
919 | struct inode *inode; | 919 | struct inode *inode; |
920 | unsigned int vm_flags; | 920 | unsigned int vm_flags; |
921 | int error; | 921 | int error; |
922 | int accountable = 1; | ||
923 | unsigned long reqprot = prot; | 922 | unsigned long reqprot = prot; |
924 | 923 | ||
925 | /* | 924 | /* |
@@ -1020,8 +1019,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
1020 | return -EPERM; | 1019 | return -EPERM; |
1021 | vm_flags &= ~VM_MAYEXEC; | 1020 | vm_flags &= ~VM_MAYEXEC; |
1022 | } | 1021 | } |
1023 | if (is_file_hugepages(file)) | ||
1024 | accountable = 0; | ||
1025 | 1022 | ||
1026 | if (!file->f_op || !file->f_op->mmap) | 1023 | if (!file->f_op || !file->f_op->mmap) |
1027 | return -ENODEV; | 1024 | return -ENODEV; |
@@ -1057,8 +1054,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
1057 | if (error) | 1054 | if (error) |
1058 | return error; | 1055 | return error; |
1059 | 1056 | ||
1060 | return mmap_region(file, addr, len, flags, vm_flags, pgoff, | 1057 | return mmap_region(file, addr, len, flags, vm_flags, pgoff); |
1061 | accountable); | ||
1062 | } | 1058 | } |
1063 | EXPORT_SYMBOL(do_mmap_pgoff); | 1059 | EXPORT_SYMBOL(do_mmap_pgoff); |
1064 | 1060 | ||
@@ -1096,17 +1092,23 @@ int vma_wants_writenotify(struct vm_area_struct *vma) | |||
1096 | 1092 | ||
1097 | /* | 1093 | /* |
1098 | * We account for memory if it's a private writeable mapping, | 1094 | * We account for memory if it's a private writeable mapping, |
1099 | * and VM_NORESERVE wasn't set. | 1095 | * not hugepages and VM_NORESERVE wasn't set. |
1100 | */ | 1096 | */ |
1101 | static inline int accountable_mapping(unsigned int vm_flags) | 1097 | static inline int accountable_mapping(struct file *file, unsigned int vm_flags) |
1102 | { | 1098 | { |
1099 | /* | ||
1100 | * hugetlb has its own accounting separate from the core VM | ||
1101 | * VM_HUGETLB may not be set yet so we cannot check for that flag. | ||
1102 | */ | ||
1103 | if (file && is_file_hugepages(file)) | ||
1104 | return 0; | ||
1105 | |||
1103 | return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; | 1106 | return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; |
1104 | } | 1107 | } |
1105 | 1108 | ||
1106 | unsigned long mmap_region(struct file *file, unsigned long addr, | 1109 | unsigned long mmap_region(struct file *file, unsigned long addr, |
1107 | unsigned long len, unsigned long flags, | 1110 | unsigned long len, unsigned long flags, |
1108 | unsigned int vm_flags, unsigned long pgoff, | 1111 | unsigned int vm_flags, unsigned long pgoff) |
1109 | int accountable) | ||
1110 | { | 1112 | { |
1111 | struct mm_struct *mm = current->mm; | 1113 | struct mm_struct *mm = current->mm; |
1112 | struct vm_area_struct *vma, *prev; | 1114 | struct vm_area_struct *vma, *prev; |
@@ -1132,18 +1134,22 @@ munmap_back: | |||
1132 | 1134 | ||
1133 | /* | 1135 | /* |
1134 | * Set 'VM_NORESERVE' if we should not account for the | 1136 | * Set 'VM_NORESERVE' if we should not account for the |
1135 | * memory use of this mapping. We only honor MAP_NORESERVE | 1137 | * memory use of this mapping. |
1136 | * if we're allowed to overcommit memory. | ||
1137 | */ | 1138 | */ |
1138 | if ((flags & MAP_NORESERVE) && sysctl_overcommit_memory != OVERCOMMIT_NEVER) | 1139 | if ((flags & MAP_NORESERVE)) { |
1139 | vm_flags |= VM_NORESERVE; | 1140 | /* We honor MAP_NORESERVE if allowed to overcommit */ |
1140 | if (!accountable) | 1141 | if (sysctl_overcommit_memory != OVERCOMMIT_NEVER) |
1141 | vm_flags |= VM_NORESERVE; | 1142 | vm_flags |= VM_NORESERVE; |
1143 | |||
1144 | /* hugetlb applies strict overcommit unless MAP_NORESERVE */ | ||
1145 | if (file && is_file_hugepages(file)) | ||
1146 | vm_flags |= VM_NORESERVE; | ||
1147 | } | ||
1142 | 1148 | ||
1143 | /* | 1149 | /* |
1144 | * Private writable mapping: check memory availability | 1150 | * Private writable mapping: check memory availability |
1145 | */ | 1151 | */ |
1146 | if (accountable_mapping(vm_flags)) { | 1152 | if (accountable_mapping(file, vm_flags)) { |
1147 | charged = len >> PAGE_SHIFT; | 1153 | charged = len >> PAGE_SHIFT; |
1148 | if (security_vm_enough_memory(charged)) | 1154 | if (security_vm_enough_memory(charged)) |
1149 | return -ENOMEM; | 1155 | return -ENOMEM; |
@@ -2082,12 +2088,8 @@ void exit_mmap(struct mm_struct *mm) | |||
2082 | unsigned long end; | 2088 | unsigned long end; |
2083 | 2089 | ||
2084 | /* mm's last user has gone, and its about to be pulled down */ | 2090 | /* mm's last user has gone, and its about to be pulled down */ |
2085 | arch_exit_mmap(mm); | ||
2086 | mmu_notifier_release(mm); | 2091 | mmu_notifier_release(mm); |
2087 | 2092 | ||
2088 | if (!mm->mmap) /* Can happen if dup_mmap() received an OOM */ | ||
2089 | return; | ||
2090 | |||
2091 | if (mm->locked_vm) { | 2093 | if (mm->locked_vm) { |
2092 | vma = mm->mmap; | 2094 | vma = mm->mmap; |
2093 | while (vma) { | 2095 | while (vma) { |
@@ -2096,7 +2098,13 @@ void exit_mmap(struct mm_struct *mm) | |||
2096 | vma = vma->vm_next; | 2098 | vma = vma->vm_next; |
2097 | } | 2099 | } |
2098 | } | 2100 | } |
2101 | |||
2102 | arch_exit_mmap(mm); | ||
2103 | |||
2099 | vma = mm->mmap; | 2104 | vma = mm->mmap; |
2105 | if (!vma) /* Can happen if dup_mmap() received an OOM */ | ||
2106 | return; | ||
2107 | |||
2100 | lru_add_drain(); | 2108 | lru_add_drain(); |
2101 | flush_cache_mm(mm); | 2109 | flush_cache_mm(mm); |
2102 | tlb = tlb_gather_mmu(mm, 1); | 2110 | tlb = tlb_gather_mmu(mm, 1); |