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>
diff --git a/ipc/msg.c b/ipc/msg.c
index 08591a0..c2ee26f 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -81,7 +81,7 @@
 	ipc_buildid(&msg_ids(ns), id, seq)
 
 static void freeque(struct ipc_namespace *, struct msg_queue *);
-static int newque (struct ipc_namespace *ns, key_t key, int msgflg);
+static int newque(struct ipc_namespace *, struct ipc_params *);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 #endif
@@ -144,10 +144,12 @@
 	ipc_rmid(&msg_ids(ns), &s->q_perm);
 }
 
-static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
+static int newque(struct ipc_namespace *ns, struct ipc_params *params)
 {
 	struct msg_queue *msq;
 	int id, retval;
+	key_t key = params->key;
+	int msgflg = params->flg;
 
 	msq = ipc_rcu_alloc(sizeof(*msq));
 	if (!msq)
@@ -264,56 +266,27 @@
 	ipc_rcu_putref(msq);
 }
 
+static inline int msg_security(void *msq, int msgflg)
+{
+	return security_msg_queue_associate((struct msg_queue *) msq, msgflg);
+}
+
 asmlinkage long sys_msgget(key_t key, int msgflg)
 {
-	struct msg_queue *msq;
-	int ret;
 	struct ipc_namespace *ns;
+	struct ipc_ops msg_ops;
+	struct ipc_params msg_params;
 
 	ns = current->nsproxy->ipc_ns;
 
-	ret = idr_pre_get(&msg_ids(ns).ipcs_idr, GFP_KERNEL);
+	msg_ops.getnew = newque;
+	msg_ops.associate = msg_security;
+	msg_ops.more_checks = NULL;
 
-	if (key == IPC_PRIVATE)  {
-		if (!ret)
-			ret = -ENOMEM;
-		else {
-			mutex_lock(&msg_ids(ns).mutex);
-			ret = newque(ns, key, msgflg);
-			mutex_unlock(&msg_ids(ns).mutex);
-		}
-	} else {
-		mutex_lock(&msg_ids(ns).mutex);
-		msq = (struct msg_queue *) ipc_findkey(&msg_ids(ns), key);
-		if (msq == NULL) {
-			/* key not used */
-			if (!(msgflg & IPC_CREAT))
-				ret = -ENOENT;
-			else if (!ret)
-				ret = -ENOMEM;
-			else
-				ret = newque(ns, key, msgflg);
-		} else {
-			/* msq has been locked by ipc_findkey() */
+	msg_params.key = key;
+	msg_params.flg = msgflg;
 
-			if (msgflg & IPC_CREAT && msgflg & IPC_EXCL)
-				ret = -EEXIST;
-			else {
-				if (ipcperms(&msq->q_perm, msgflg))
-					ret = -EACCES;
-				else {
-					ret = security_msg_queue_associate(
-								msq, msgflg);
-					if (!ret)
-						ret = msq->q_perm.id;
-				}
-			}
-			msg_unlock(msq);
-		}
-		mutex_unlock(&msg_ids(ns).mutex);
-	}
-
-	return ret;
+	return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params);
 }
 
 static inline unsigned long