aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipc/shm.c240
1 files changed, 155 insertions, 85 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index 5bb617f6306e..eb57e2254304 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -37,11 +37,21 @@
37#include <linux/seq_file.h> 37#include <linux/seq_file.h>
38#include <linux/mutex.h> 38#include <linux/mutex.h>
39#include <linux/nsproxy.h> 39#include <linux/nsproxy.h>
40#include <linux/mount.h>
40 41
41#include <asm/uaccess.h> 42#include <asm/uaccess.h>
42 43
43#include "util.h" 44#include "util.h"
44 45
46struct shm_file_data {
47 int id;
48 struct ipc_namespace *ns;
49 struct file *file;
50 const struct vm_operations_struct *vm_ops;
51};
52
53#define shm_file_data(file) (*((struct shm_file_data **)&(file)->private_data))
54
45static const struct file_operations shm_file_operations; 55static const struct file_operations shm_file_operations;
46static struct vm_operations_struct shm_vm_ops; 56static struct vm_operations_struct shm_vm_ops;
47 57
@@ -60,8 +70,8 @@ static struct ipc_ids init_shm_ids;
60 70
61static int newseg (struct ipc_namespace *ns, key_t key, 71static int newseg (struct ipc_namespace *ns, key_t key,
62 int shmflg, size_t size); 72 int shmflg, size_t size);
63static void shm_open (struct vm_area_struct *shmd); 73static void shm_open(struct vm_area_struct *vma);
64static void shm_close (struct vm_area_struct *shmd); 74static void shm_close(struct vm_area_struct *vma);
65static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp); 75static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
66#ifdef CONFIG_PROC_FS 76#ifdef CONFIG_PROC_FS
67static int sysvipc_shm_proc_show(struct seq_file *s, void *it); 77static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
@@ -150,11 +160,14 @@ static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp)
150 160
151 161
152 162
153static inline void shm_inc(struct ipc_namespace *ns, int id) 163/* This is called by fork, once for every shm attach. */
164static void shm_open(struct vm_area_struct *vma)
154{ 165{
166 struct file *file = vma->vm_file;
167 struct shm_file_data *sfd = shm_file_data(file);
155 struct shmid_kernel *shp; 168 struct shmid_kernel *shp;
156 169
157 shp = shm_lock(ns, id); 170 shp = shm_lock(sfd->ns, sfd->id);
158 BUG_ON(!shp); 171 BUG_ON(!shp);
159 shp->shm_atim = get_seconds(); 172 shp->shm_atim = get_seconds();
160 shp->shm_lprid = current->tgid; 173 shp->shm_lprid = current->tgid;
@@ -162,15 +175,6 @@ static inline void shm_inc(struct ipc_namespace *ns, int id)
162 shm_unlock(shp); 175 shm_unlock(shp);
163} 176}
164 177
165#define shm_file_ns(file) (*((struct ipc_namespace **)&(file)->private_data))
166
167/* This is called by fork, once for every shm attach. */
168static void shm_open(struct vm_area_struct *shmd)
169{
170 shm_inc(shm_file_ns(shmd->vm_file),
171 shmd->vm_file->f_path.dentry->d_inode->i_ino);
172}
173
174/* 178/*
175 * shm_destroy - free the struct shmid_kernel 179 * shm_destroy - free the struct shmid_kernel
176 * 180 *
@@ -195,23 +199,21 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
195} 199}
196 200
197/* 201/*
198 * remove the attach descriptor shmd. 202 * remove the attach descriptor vma.
199 * free memory for segment if it is marked destroyed. 203 * free memory for segment if it is marked destroyed.
200 * The descriptor has already been removed from the current->mm->mmap list 204 * The descriptor has already been removed from the current->mm->mmap list
201 * and will later be kfree()d. 205 * and will later be kfree()d.
202 */ 206 */
203static void shm_close (struct vm_area_struct *shmd) 207static void shm_close(struct vm_area_struct *vma)
204{ 208{
205 struct file * file = shmd->vm_file; 209 struct file * file = vma->vm_file;
206 int id = file->f_path.dentry->d_inode->i_ino; 210 struct shm_file_data *sfd = shm_file_data(file);
207 struct shmid_kernel *shp; 211 struct shmid_kernel *shp;
208 struct ipc_namespace *ns; 212 struct ipc_namespace *ns = sfd->ns;
209
210 ns = shm_file_ns(file);
211 213
212 mutex_lock(&shm_ids(ns).mutex); 214 mutex_lock(&shm_ids(ns).mutex);
213 /* remove from the list of attaches of the shm segment */ 215 /* remove from the list of attaches of the shm segment */
214 shp = shm_lock(ns, id); 216 shp = shm_lock(ns, sfd->id);
215 BUG_ON(!shp); 217 BUG_ON(!shp);
216 shp->shm_lprid = current->tgid; 218 shp->shm_lprid = current->tgid;
217 shp->shm_dtim = get_seconds(); 219 shp->shm_dtim = get_seconds();
@@ -224,46 +226,91 @@ static void shm_close (struct vm_area_struct *shmd)
224 mutex_unlock(&shm_ids(ns).mutex); 226 mutex_unlock(&shm_ids(ns).mutex);
225} 227}
226 228
229struct page *shm_nopage(struct vm_area_struct *vma, unsigned long address,
230 int *type)
231{
232 struct file *file = vma->vm_file;
233 struct shm_file_data *sfd = shm_file_data(file);
234
235 return sfd->vm_ops->nopage(vma, address, type);
236}
237
238#ifdef CONFIG_NUMA
239int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
240{
241 struct file *file = vma->vm_file;
242 struct shm_file_data *sfd = shm_file_data(file);
243 int err = 0;
244 if (sfd->vm_ops->set_policy)
245 err = sfd->vm_ops->set_policy(vma, new);
246 return err;
247}
248
249struct mempolicy *shm_get_policy(struct vm_area_struct *vma, unsigned long addr)
250{
251 struct file *file = vma->vm_file;
252 struct shm_file_data *sfd = shm_file_data(file);
253 struct mempolicy *pol = NULL;
254
255 if (sfd->vm_ops->get_policy)
256 pol = sfd->vm_ops->get_policy(vma, addr);
257 else
258 pol = vma->vm_policy;
259 return pol;
260}
261#endif
262
227static int shm_mmap(struct file * file, struct vm_area_struct * vma) 263static int shm_mmap(struct file * file, struct vm_area_struct * vma)
228{ 264{
265 struct shm_file_data *sfd = shm_file_data(file);
229 int ret; 266 int ret;
230 267
231 ret = shmem_mmap(file, vma); 268 ret = sfd->file->f_op->mmap(sfd->file, vma);
232 if (ret == 0) { 269 if (ret != 0)
233 vma->vm_ops = &shm_vm_ops; 270 return ret;
234 if (!(vma->vm_flags & VM_WRITE)) 271 sfd->vm_ops = vma->vm_ops;
235 vma->vm_flags &= ~VM_MAYWRITE; 272 vma->vm_ops = &shm_vm_ops;
236 shm_inc(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino); 273 shm_open(vma);
237 }
238 274
239 return ret; 275 return ret;
240} 276}
241 277
242static int shm_release(struct inode *ino, struct file *file) 278static int shm_release(struct inode *ino, struct file *file)
243{ 279{
244 struct ipc_namespace *ns; 280 struct shm_file_data *sfd = shm_file_data(file);
245 281
246 ns = shm_file_ns(file); 282 put_ipc_ns(sfd->ns);
247 put_ipc_ns(ns); 283 shm_file_data(file) = NULL;
248 shm_file_ns(file) = NULL; 284 kfree(sfd);
249 return 0; 285 return 0;
250} 286}
251 287
288#ifndef CONFIG_MMU
289static unsigned long shm_get_unmapped_area(struct file *file,
290 unsigned long addr, unsigned long len, unsigned long pgoff,
291 unsigned long flags)
292{
293 struct shm_file_data *sfd = shm_file_data(file);
294 return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len, pgoff,
295 flags);
296}
297#else
298#define shm_get_unmapped_area NULL
299#endif
300
252static const struct file_operations shm_file_operations = { 301static const struct file_operations shm_file_operations = {
253 .mmap = shm_mmap, 302 .mmap = shm_mmap,
254 .release = shm_release, 303 .release = shm_release,
255#ifndef CONFIG_MMU 304 .get_unmapped_area = shm_get_unmapped_area,
256 .get_unmapped_area = shmem_get_unmapped_area,