Commit 2cafed30 authored by Davidlohr Bueso's avatar Davidlohr Bueso Committed by Linus Torvalds

ipc,msg: introduce msgctl_nolock

Similar to semctl, when calling msgctl, the *_INFO and *_STAT commands
can be performed without acquiring the ipc object.

Add a msgctl_nolock() function and move the logic of *_INFO and *_STAT
out of msgctl().  This change still takes the lock and it will be
properly lockless in the next patch
Signed-off-by: default avatarDavidlohr Bueso <davidlohr.bueso@hp.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Rik van Riel <riel@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 15724ecb
...@@ -467,17 +467,11 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, ...@@ -467,17 +467,11 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
return err; return err;
} }
SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
int cmd, int version, void __user *buf)
{ {
int err;
struct msg_queue *msq; struct msg_queue *msq;
int err, version;
struct ipc_namespace *ns;
if (msqid < 0 || cmd < 0)
return -EINVAL;
version = ipc_parse_version(&cmd);
ns = current->nsproxy->ipc_ns;
switch (cmd) { switch (cmd) {
case IPC_INFO: case IPC_INFO:
...@@ -488,6 +482,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) ...@@ -488,6 +482,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
if (!buf) if (!buf)
return -EFAULT; return -EFAULT;
/* /*
* We must not return kernel stack data. * We must not return kernel stack data.
* due to padding, it's not enough * due to padding, it's not enough
...@@ -519,7 +514,8 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) ...@@ -519,7 +514,8 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
return -EFAULT; return -EFAULT;
return (max_id < 0) ? 0 : max_id; return (max_id < 0) ? 0 : max_id;
} }
case MSG_STAT: /* msqid is an index rather than a msg queue id */
case MSG_STAT:
case IPC_STAT: case IPC_STAT:
{ {
struct msqid64_ds tbuf; struct msqid64_ds tbuf;
...@@ -563,19 +559,42 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) ...@@ -563,19 +559,42 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
return -EFAULT; return -EFAULT;
return success_return; return success_return;
} }
case IPC_SET:
case IPC_RMID:
err = msgctl_down(ns, msqid, cmd, buf, version);
return err;
default: default:
return -EINVAL; return -EINVAL;
} }
return err;
out_unlock: out_unlock:
msg_unlock(msq); msg_unlock(msq);
return err; return err;
} }
SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
{
int version;
struct ipc_namespace *ns;
if (msqid < 0 || cmd < 0)
return -EINVAL;
version = ipc_parse_version(&cmd);
ns = current->nsproxy->ipc_ns;
switch (cmd) {
case IPC_INFO:
case MSG_INFO:
case MSG_STAT: /* msqid is an index rather than a msg queue id */
case IPC_STAT:
return msgctl_nolock(ns, msqid, cmd, version, buf);
case IPC_SET:
case IPC_RMID:
return msgctl_down(ns, msqid, cmd, buf, version);
default:
return -EINVAL;
}
}
static int testmsg(struct msg_msg *msg, long type, int mode) static int testmsg(struct msg_msg *msg, long type, int mode)
{ {
switch(mode) switch(mode)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment