diff options
author | Davidlohr Bueso <davidlohr.bueso@hp.com> | 2013-07-08 19:01:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-09 13:33:27 -0400 |
commit | 2cafed30f150f7314f98717b372df8173516cae0 (patch) | |
tree | 21f2440948b12d2905d1c2ded7fcc7f88e980360 /ipc | |
parent | 15724ecb7e9bab35fc694c666ad563adba820cc3 (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.c | 49 |
1 files changed, 34 insertions, 15 deletions
@@ -467,17 +467,11 @@ out_up: | |||
467 | return err; | 467 | return err; |
468 | } | 468 | } |
469 | 469 | ||
470 | SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) | 470 | static 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; | ||
574 | out_unlock: | 568 | out_unlock: |
575 | msg_unlock(msq); | 569 | msg_unlock(msq); |
576 | return err; | 570 | return err; |
577 | } | 571 | } |
578 | 572 | ||
573 | SYSCALL_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 | |||
579 | static int testmsg(struct msg_msg *msg, long type, int mode) | 598 | static int testmsg(struct msg_msg *msg, long type, int mode) |
580 | { | 599 | { |
581 | switch(mode) | 600 | switch(mode) |