diff options
author | Nadia Derbey <Nadia.Derbey@bull.net> | 2007-10-18 23:40:49 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 11:53:44 -0700 |
commit | 7748dbfaa010b12d5fb9ddf80199534c565c6bce (patch) | |
tree | c6756de4007c29fdcb405d54173a4322d48ff631 /ipc/shm.c | |
parent | 7ca7e564e049d8b350ec9d958ff25eaa24226352 (diff) | |
download | lwn-7748dbfaa010b12d5fb9ddf80199534c565c6bce.tar.gz lwn-7748dbfaa010b12d5fb9ddf80199534c565c6bce.zip |
ipc: unify the syscalls code
This patch introduces a change into the sys_msgget(), sys_semget() and
sys_shmget() routines: they now share a common code, which is better for
maintainability.
Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/shm.c')
-rw-r--r-- | ipc/shm.c | 73 |
1 files changed, 27 insertions, 46 deletions
diff --git a/ipc/shm.c b/ipc/shm.c index dcc333239683..d20cc25c5bdf 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -68,8 +68,7 @@ static struct ipc_ids init_shm_ids; #define shm_buildid(ns, id, seq) \ ipc_buildid(&shm_ids(ns), id, seq) -static int newseg (struct ipc_namespace *ns, key_t key, - int shmflg, size_t size); +static int newseg(struct ipc_namespace *, struct ipc_params *); static void shm_open(struct vm_area_struct *vma); static void shm_close(struct vm_area_struct *vma); static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp); @@ -341,8 +340,11 @@ static struct vm_operations_struct shm_vm_ops = { #endif }; -static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size) +static int newseg(struct ipc_namespace *ns, struct ipc_params *params) { + key_t key = params->key; + int shmflg = params->flg; + size_t size = params->u.size; int error; struct shmid_kernel *shp; int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT; @@ -423,57 +425,36 @@ no_file: return error; } +static inline int shm_security(void *shp, int shmflg) +{ + return security_shm_associate((struct shmid_kernel *) shp, shmflg); +} + +static inline int shm_more_checks(void *shp, struct ipc_params *params) +{ + if (((struct shmid_kernel *)shp)->shm_segsz < params->u.size) + return -EINVAL; + + return 0; +} + asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) { - struct shmid_kernel *shp; - int err; struct ipc_namespace *ns; + struct ipc_ops shm_ops; + struct ipc_params shm_params; ns = current->nsproxy->ipc_ns; - err = idr_pre_get(&shm_ids(ns).ipcs_idr, GFP_KERNEL); + shm_ops.getnew = newseg; + shm_ops.associate = shm_security; + shm_ops.more_checks = shm_more_checks; - if (key == IPC_PRIVATE) { - if (!err) - err = -ENOMEM; - else { - mutex_lock(&shm_ids(ns).mutex); - err = newseg(ns, key, shmflg, size); - mutex_unlock(&shm_ids(ns).mutex); - } - } else { - mutex_lock(&shm_ids(ns).mutex); - shp = (struct shmid_kernel *) ipc_findkey(&shm_ids(ns), key); - if (shp == NULL) { - if (!(shmflg & IPC_CREAT)) - err = -ENOENT; - else if (!err) - err = -ENOMEM; - else - err = newseg(ns, key, shmflg, size); - } else { - /* shp has been locked by ipc_findkey() */ - - if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) - err = -EEXIST; - else { - if (shp->shm_segsz < size) - err = -EINVAL; - else if (ipcperms(&shp->shm_perm, shmflg)) - err = -EACCES; - else { - err = security_shm_associate(shp, - shmflg); - if (!err) - err = shp->shm_perm.id; - } - } - shm_unlock(shp); - } - mutex_unlock(&shm_ids(ns).mutex); - } + shm_params.key = key; + shm_params.flg = shmflg; + shm_params.u.size = size; - return err; + return ipcget(ns, &shm_ids(ns), &shm_ops, &shm_params); } static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version) |