diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-31 18:08:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-31 18:08:56 -0500 |
commit | fc8744adc870a8d4366908221508bb113d8b72ee (patch) | |
tree | 755f4c4a1cc30567fde4e60c9cc5e6a889c360b0 | |
parent | 33bfad54b58cf05cfe6678c3ec9235d4bc8db4c2 (diff) |
Stop playing silly games with the VM_ACCOUNT flag
The mmap_region() code would temporarily set the VM_ACCOUNT flag for
anonymous shared mappings just to inform shmem_zero_setup() that it
should enable accounting for the resulting shm object. It would then
clear the flag after calling ->mmap (for the /dev/zero case) or doing
shmem_zero_setup() (for the MAP_ANON case).
This just resulted in vma merge issues, but also made for just
unnecessary confusion. Use the already-existing VM_NORESERVE flag for
this instead, and let shmem_{zero|file}_setup() just figure it out from
that.
This also happens to make it obvious that the new DRI2 GEM layer uses a
non-reserving backing store for its object allocation - which is quite
possibly not intentional. But since I didn't want to change semantics
in this patch, I left it alone, and just updated the caller to use the
new flag semantics.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 2 | ||||
-rw-r--r-- | ipc/shm.c | 4 | ||||
-rw-r--r-- | mm/mmap.c | 48 | ||||
-rw-r--r-- | mm/shmem.c | 2 |
4 files changed, 29 insertions, 27 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 9da581452874..6915fb82d0b0 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -136,7 +136,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) | |||
136 | obj = kcalloc(1, sizeof(*obj), GFP_KERNEL); | 136 | obj = kcalloc(1, sizeof(*obj), GFP_KERNEL); |
137 | 137 | ||
138 | obj->dev = dev; | 138 | obj->dev = dev; |
139 | obj->filp = shmem_file_setup("drm mm object", size, 0); | 139 | obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); |
140 | if (IS_ERR(obj->filp)) { | 140 | if (IS_ERR(obj->filp)) { |
141 | kfree(obj); | 141 | kfree(obj); |
142 | return NULL; | 142 | return NULL; |
@@ -368,14 +368,14 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
368 | file = hugetlb_file_setup(name, size); | 368 | file = hugetlb_file_setup(name, size); |
369 | shp->mlock_user = current_user(); | 369 | shp->mlock_user = current_user(); |
370 | } else { | 370 | } else { |
371 | int acctflag = VM_ACCOUNT; | 371 | int acctflag = 0; |
372 | /* | 372 | /* |
373 | * Do not allow no accounting for OVERCOMMIT_NEVER, even | 373 | * Do not allow no accounting for OVERCOMMIT_NEVER, even |
374 | * if it's asked for. | 374 | * if it's asked for. |
375 | */ | 375 | */ |
376 | if ((shmflg & SHM_NORESERVE) && | 376 | if ((shmflg & SHM_NORESERVE) && |
377 | sysctl_overcommit_memory != OVERCOMMIT_NEVER) | 377 | sysctl_overcommit_memory != OVERCOMMIT_NEVER) |
378 | acctflag = 0; | 378 | acctflag = VM_NORESERVE; |
379 | file = shmem_file_setup(name, size, acctflag); | 379 | file = shmem_file_setup(name, size, acctflag); |
380 | } | 380 | } |
381 | error = PTR_ERR(file); | 381 | error = PTR_ERR(file); |
@@ -1090,6 +1090,15 @@ int vma_wants_writenotify(struct vm_area_struct *vma) | |||
1090 | mapping_cap_account_dirty(vma->vm_file->f_mapping); | 1090 | mapping_cap_account_dirty(vma->vm_file->f_mapping); |
1091 | } | 1091 | } |
1092 | 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 | |||
1093 | unsigned long mmap_region(struct file *file, unsigned long addr, | 1102 | unsigned long mmap_region(struct file *file, unsigned long addr, |
1094 | unsigned long len, unsigned long flags, | 1103 | unsigned long len, unsigned long flags, |
1095 | unsigned int vm_flags, unsigned long pgoff, | 1104 | unsigned int vm_flags, unsigned long pgoff, |
@@ -1117,23 +1126,24 @@ munmap_back: | |||
1117 | if (!may_expand_vm(mm, len >> PAGE_SHIFT)) | 1126 | if (!may_expand_vm(mm, len >> PAGE_SHIFT)) |
1118 | return -ENOMEM; | 1127 | return -ENOMEM; |
1119 | 1128 | ||
1120 | 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) | ||
1121 | vm_flags |= VM_NORESERVE; | 1137 | vm_flags |= VM_NORESERVE; |
1122 | 1138 | ||
1123 | if (accountable && (!(flags & MAP_NORESERVE) || | 1139 | /* |
1124 | sysctl_overcommit_memory == OVERCOMMIT_NEVER)) { | 1140 | * Private writable mapping: check memory availability |
1125 | if (vm_flags & VM_SHARED) { | 1141 | */ |
1126 | /* Check memory availability in shmem_file_setup? */ | 1142 | if (accountable_mapping(vm_flags)) { |
1127 | vm_flags |= VM_ACCOUNT; | 1143 | charged = len >> PAGE_SHIFT; |
1128 | } else if (vm_flags & VM_WRITE) { | 1144 | if (security_vm_enough_memory(charged)) |
1129 | /* | 1145 | return -ENOMEM; |
1130 | * Private writable mapping: check memory availability | 1146 | vm_flags |= VM_ACCOUNT; |
1131 | */ | ||
1132 | charged = len >> PAGE_SHIFT; | ||
1133 | if (security_vm_enough_memory(charged)) | ||
1134 | return -ENOMEM; | ||
1135 | vm_flags |= VM_ACCOUNT; | ||
1136 | } | ||
1137 | } | 1147 | } |
1138 | 1148 | ||
1139 | /* | 1149 | /* |
@@ -1184,14 +1194,6 @@ munmap_back: | |||
1184 | goto free_vma; | 1194 | goto free_vma; |
1185 | } | 1195 | } |
1186 | 1196 | ||
1187 | /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform | ||
1188 | * shmem_zero_setup (perhaps called through /dev/zero's ->mmap) | ||
1189 | * that memory reservation must be checked; but that reservation | ||
1190 | * belongs to shared memory object, not to vma: so now clear it. | ||
1191 | */ | ||
1192 | if ((vm_flags & (VM_SHARED|VM_ACCOUNT)) == (VM_SHARED|VM_ACCOUNT)) | ||
1193 | vma->vm_flags &= ~VM_ACCOUNT; | ||
1194 | |||
1195 | /* Can addr have changed?? | 1197 | /* Can addr have changed?? |
1196 | * | 1198 | * |
1197 | * Answer: Yes, several device drivers can do it in their | 1199 | * Answer: Yes, several device drivers can do it in their |
diff --git a/mm/shmem.c b/mm/shmem.c index 5d0de96c9789..19d566ccdeea 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -2628,7 +2628,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) | |||
2628 | goto close_file; | 2628 | goto close_file; |
2629 | 2629 | ||
2630 | #ifdef CONFIG_SHMEM | 2630 | #ifdef CONFIG_SHMEM |
2631 | SHMEM_I(inode)->flags = flags & VM_ACCOUNT; | 2631 | SHMEM_I(inode)->flags = (flags & VM_NORESERVE) ? 0 : VM_ACCOUNT; |
2632 | #endif | 2632 | #endif |
2633 | d_instantiate(dentry, inode); | 2633 | d_instantiate(dentry, inode); |
2634 | inode->i_size = size; | 2634 | inode->i_size = size; |