diff options
Diffstat (limited to 'mm/mmap.c')
-rw-r--r-- | mm/mmap.c | 53 |
1 files changed, 29 insertions, 24 deletions
@@ -658,6 +658,9 @@ again: remove_next = 1 + (end > next->vm_end); | |||
658 | validate_mm(mm); | 658 | validate_mm(mm); |
659 | } | 659 | } |
660 | 660 | ||
661 | /* Flags that can be inherited from an existing mapping when merging */ | ||
662 | #define VM_MERGEABLE_FLAGS (VM_CAN_NONLINEAR) | ||
663 | |||
661 | /* | 664 | /* |
662 | * If the vma has a ->close operation then the driver probably needs to release | 665 | * If the vma has a ->close operation then the driver probably needs to release |
663 | * per-vma resources, so we don't attempt to merge those. | 666 | * per-vma resources, so we don't attempt to merge those. |
@@ -665,7 +668,7 @@ again: remove_next = 1 + (end > next->vm_end); | |||
665 | static inline int is_mergeable_vma(struct vm_area_struct *vma, | 668 | static inline int is_mergeable_vma(struct vm_area_struct *vma, |
666 | struct file *file, unsigned long vm_flags) | 669 | struct file *file, unsigned long vm_flags) |
667 | { | 670 | { |
668 | if (vma->vm_flags != vm_flags) | 671 | if ((vma->vm_flags ^ vm_flags) & ~VM_MERGEABLE_FLAGS) |
669 | return 0; | 672 | return 0; |
670 | if (vma->vm_file != file) | 673 | if (vma->vm_file != file) |
671 | return 0; | 674 | return 0; |
@@ -1087,6 +1090,15 @@ int vma_wants_writenotify(struct vm_area_struct *vma) | |||
1087 | mapping_cap_account_dirty(vma->vm_file->f_mapping); | 1090 | mapping_cap_account_dirty(vma->vm_file->f_mapping); |
1088 | } | 1091 | } |
1089 | 1092 | ||
1093 | /* | ||
1094 | * We account for memory if it's a private writeable mapping, | ||
1095 | * and VM_NORESERVE wasn't set. | ||
1096 | */ | ||
1097 | static inline int accountable_mapping(unsigned int vm_flags) | ||
1098 | { | ||
1099 | return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; | ||
1100 | } | ||
1101 | |||
1090 | unsigned long mmap_region(struct file *file, unsigned long addr, | 1102 | unsigned long mmap_region(struct file *file, unsigned long addr, |
1091 | unsigned long len, unsigned long flags, | 1103 | unsigned long len, unsigned long flags, |
1092 | unsigned int vm_flags, unsigned long pgoff, | 1104 | unsigned int vm_flags, unsigned long pgoff, |
@@ -1114,23 +1126,24 @@ munmap_back: | |||
1114 | if (!may_expand_vm(mm, len >> PAGE_SHIFT)) | 1126 | if (!may_expand_vm(mm, len >> PAGE_SHIFT)) |
1115 | return -ENOMEM; | 1127 | return -ENOMEM; |
1116 | 1128 | ||
1117 | if (flags & MAP_NORESERVE) | 1129 | /* |
1130 | * Set 'VM_NORESERVE' if we should not account for the | ||
1131 | * memory use of this mapping. We only honor MAP_NORESERVE | ||
1132 | * if we're allowed to overcommit memory. | ||
1133 | */ | ||
1134 | if ((flags & MAP_NORESERVE) && sysctl_overcommit_memory != OVERCOMMIT_NEVER) | ||
1135 | vm_flags |= VM_NORESERVE; | ||
1136 | if (!accountable) | ||
1118 | vm_flags |= VM_NORESERVE; | 1137 | vm_flags |= VM_NORESERVE; |
1119 | 1138 | ||
1120 | if (accountable && (!(flags & MAP_NORESERVE) || | 1139 | /* |
1121 | sysctl_overcommit_memory == OVERCOMMIT_NEVER)) { | 1140 | * Private writable mapping: check memory availability |
1122 | if (vm_flags & VM_SHARED) { | 1141 | */ |
1123 | /* Check memory availability in shmem_file_setup? */ | 1142 | if (accountable_mapping(vm_flags)) { |
1124 | vm_flags |= VM_ACCOUNT; | 1143 | charged = len >> PAGE_SHIFT; |
1125 | } else if (vm_flags & VM_WRITE) { | 1144 | if (security_vm_enough_memory(charged)) |
1126 | /* | 1145 | return -ENOMEM; |
1127 | * Private writable mapping: check memory availability | 1146 | vm_flags |= VM_ACCOUNT; |
1128 | */ | ||
1129 | charged = len >> PAGE_SHIFT; | ||
1130 | if (security_vm_enough_memory(charged)) | ||
1131 | return -ENOMEM; | ||
1132 | vm_flags |= VM_ACCOUNT; | ||
1133 | } | ||
1134 | } | 1147 | } |
1135 | 1148 | ||
1136 | /* | 1149 | /* |
@@ -1181,14 +1194,6 @@ munmap_back: | |||
1181 | goto free_vma; | 1194 | goto free_vma; |
1182 | } | 1195 | } |
1183 | 1196 | ||
1184 | /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform | ||
1185 | * shmem_zero_setup (perhaps called through /dev/zero's ->mmap) | ||
1186 | * that memory reservation must be checked; but that reservation | ||
1187 | * belongs to shared memory object, not to vma: so now clear it. | ||
1188 | */ | ||
1189 | if ((vm_flags & (VM_SHARED|VM_ACCOUNT)) == (VM_SHARED|VM_ACCOUNT)) | ||
1190 | vma->vm_flags &= ~VM_ACCOUNT; | ||
1191 | |||
1192 | /* Can addr have changed?? | 1197 | /* Can addr have changed?? |
1193 | * | 1198 | * |
1194 | * Answer: Yes, several device drivers can do it in their | 1199 | * Answer: Yes, several device drivers can do it in their |