diff options
| author | Davidlohr Bueso <davidlohr.bueso@hp.com> | 2013-07-08 19:01:13 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-09 13:33:27 -0400 |
| commit | 15724ecb7e9bab35fc694c666ad563adba820cc3 (patch) | |
| tree | d9ae089252e84327367056a29c0cf6b16f844c2e /ipc | |
| parent | 7b4cc5d8411bd4e9d61d8714f53859740cf830c2 (diff) | |
ipc,msg: shorten critical region in msgctl_down
Instead of holding the ipc lock for the entire function, use the
ipcctl_pre_down_nolock and only acquire the lock for specific commands:
RMID and SET.
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 | 12 |
1 files changed, 7 insertions, 5 deletions
| @@ -410,11 +410,10 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, | |||
| 410 | down_write(&msg_ids(ns).rw_mutex); | 410 | down_write(&msg_ids(ns).rw_mutex); |
| 411 | rcu_read_lock(); | 411 | rcu_read_lock(); |
| 412 | 412 | ||
| 413 | ipcp = ipcctl_pre_down(ns, &msg_ids(ns), msqid, cmd, | 413 | ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd, |
| 414 | &msqid64.msg_perm, msqid64.msg_qbytes); | 414 | &msqid64.msg_perm, msqid64.msg_qbytes); |
| 415 | if (IS_ERR(ipcp)) { | 415 | if (IS_ERR(ipcp)) { |
| 416 | err = PTR_ERR(ipcp); | 416 | err = PTR_ERR(ipcp); |
| 417 | /* the ipc lock is not held upon failure */ | ||
| 418 | goto out_unlock1; | 417 | goto out_unlock1; |
| 419 | } | 418 | } |
| 420 | 419 | ||
| @@ -422,10 +421,11 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, | |||
| 422 | 421 | ||
| 423 | err = security_msg_queue_msgctl(msq, cmd); | 422 | err = security_msg_queue_msgctl(msq, cmd); |
| 424 | if (err) | 423 | if (err) |
| 425 | goto out_unlock0; | 424 | goto out_unlock1; |
| 426 | 425 | ||
| 427 | switch (cmd) { | 426 | switch (cmd) { |
| 428 | case IPC_RMID: | 427 | case IPC_RMID: |
| 428 | ipc_lock_object(&msq->q_perm); | ||
| 429 | /* freeque unlocks the ipc object and rcu */ | 429 | /* freeque unlocks the ipc object and rcu */ |
| 430 | freeque(ns, ipcp); | 430 | freeque(ns, ipcp); |
| 431 | goto out_up; | 431 | goto out_up; |
| @@ -433,9 +433,10 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, | |||
| 433 | if (msqid64.msg_qbytes > ns->msg_ctlmnb && | 433 | if (msqid64.msg_qbytes > ns->msg_ctlmnb && |
| 434 | !capable(CAP_SYS_RESOURCE)) { | 434 | !capable(CAP_SYS_RESOURCE)) { |
| 435 | err = -EPERM; | 435 | err = -EPERM; |
| 436 | goto out_unlock0; | 436 | goto out_unlock1; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | ipc_lock_object(&msq->q_perm); | ||
| 439 | err = ipc_update_perm(&msqid64.msg_perm, ipcp); | 440 | err = ipc_update_perm(&msqid64.msg_perm, ipcp); |
| 440 | if (err) | 441 | if (err) |
| 441 | goto out_unlock0; | 442 | goto out_unlock0; |
| @@ -454,6 +455,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, | |||
| 454 | break; | 455 | break; |
| 455 | default: | 456 | default: |
| 456 | err = -EINVAL; | 457 | err = -EINVAL; |
| 458 | goto out_unlock1; | ||
| 457 | } | 459 | } |
| 458 | 460 | ||
| 459 | out_unlock0: | 461 | out_unlock0: |
