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:

committed by
Linus Torvalds

parent
7ca7e564e0
commit
7748dbfaa0
73
ipc/shm.c
73
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() */
|
||||
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)
|
||||
|
Reference in New Issue
Block a user