aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-31 18:08:56 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-31 18:08:56 -0500
commitfc8744adc870a8d4366908221508bb113d8b72ee (patch)
tree755f4c4a1cc30567fde4e60c9cc5e6a889c360b0
parent33bfad54b58cf05cfe6678c3ec9235d4bc8db4c2 (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.c2
-rw-r--r--ipc/shm.c4
-rw-r--r--mm/mmap.c48
-rw-r--r--mm/shmem.c2
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;
diff --git a/ipc/shm.c b/ipc/shm.c
index a9e09ad2263e..c0a021f7f41a 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -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);
diff --git a/mm/mmap.c b/mm/mmap.c
index c581df14d0de..214b6a258eeb 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -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 */
1097static inline int accountable_mapping(unsigned int vm_flags)
1098{
1099 return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE;
1100}
1101
1093unsigned long mmap_region(struct file *file, unsigned long addr, 1102unsigned 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;