aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorDavidlohr Bueso <davidlohr.bueso@hp.com>2013-07-08 19:01:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 13:33:27 -0400
commit2cafed30f150f7314f98717b372df8173516cae0 (patch)
tree21f2440948b12d2905d1c2ded7fcc7f88e980360 /ipc
parent15724ecb7e9bab35fc694c666ad563adba820cc3 (diff)
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>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/msg.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index de422ff71c87..f45be81f6de9 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -467,17 +467,11 @@ out_up:
467 return err; 467 return err;
468} 468}
469 469
470SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) 470static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
471 int cmd, int version, void __user *buf)
471{ 472{
473 int err;
472 struct msg_queue *msq; 474 struct msg_queue *msq;
473 int err, version;
474 struct ipc_namespace *ns;
475
476 if (msqid < 0 || cmd < 0)
477 return -EINVAL;
478
479 version = ipc_parse_version(&cmd);
480 ns = current->nsproxy->ipc_ns;
481 475
482 switch (cmd) { 476 switch (cmd) {
483 case IPC_INFO: 477 case IPC_INFO:
@@ -488,6 +482,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
488 482
489 if (!buf) 483 if (!buf)
490 return -EFAULT; 484 return -EFAULT;
485
491 /* 486 /*
492 * We must not return kernel stack data. 487 * We must not return kernel stack data.
493 * due to padding, it's not enough 488 * due to padding, it's not enough
@@ -519,7 +514,8 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
519 return -EFAULT; 514 return -EFAULT;
520 return (max_id < 0) ? 0 : max_id; 515 return (max_id < 0) ? 0 : max_id;
521 } 516 }
522 case MSG_STAT: /* msqid is an index rather than a msg queue id */ 517
518 case MSG_STAT:
523 case IPC_STAT: 519 case IPC_STAT:
524 { 520 {
525 struct msqid64_ds tbuf; 521 struct msqid64_ds tbuf;
@@ -563,19 +559,42 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
563 return -EFAULT; 559 return -EFAULT;
564 return success_return; 560 return success_return;
565 } 561 }
566 case IPC_SET: 562
567 case IPC_RMID:
568 err = msgctl_down(ns, msqid, cmd, buf, version);
569 return err;
570 default: 563 default:
571 return -EINVAL; 564 return -EINVAL;
572 } 565 }
573 566
567 return err;
574out_unlock: 568out_unlock:
575 msg_unlock(msq); 569 msg_unlock(msq);
576 return err; 570 return err;
577} 571}
578 572
573SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
574{
575 int version;
576 struct ipc_namespace *ns;
577
578 if (msqid < 0 || cmd < 0)
579 return -EINVAL;
580
581 version = ipc_parse_version(&cmd);
582 ns = current->nsproxy->ipc_ns;
583
584 switch (cmd) {
585 case IPC_INFO:
586 case MSG_INFO:
587 case MSG_STAT: /* msqid is an index rather than a msg queue id */
588 case IPC_STAT:
589 return msgctl_nolock(ns, msqid, cmd, version, buf);
590 case IPC_SET:
591 case IPC_RMID:
592 return msgctl_down(ns, msqid, cmd, buf, version);
593 default:
594 return -EINVAL;
595 }
596}
597
579static int testmsg(struct msg_msg *msg, long type, int mode) 598static int testmsg(struct msg_msg *msg, long type, int mode)
580{ 599{
581 switch(mode) 600 switch(mode)