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>
This commit is contained in:
Nadia Derbey
2007-10-18 23:40:49 -07:00
committed by Linus Torvalds
parent 7ca7e564e0
commit 7748dbfaa0
5 changed files with 215 additions and 139 deletions

View File

@@ -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() */
shm_params.key = key;
shm_params.flg = shmflg;
shm_params.u.size = size;
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);
}
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)