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: Davidlohr Bueso <davidlohr.bueso@hp.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
15724ecb7e
commit
2cafed30f1
1 changed files with 34 additions and 15 deletions
49
ipc/msg.c
49
ipc/msg.c
|
@ -467,17 +467,11 @@ out_up:
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
Loading…
Add table
Reference in a new issue