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/msg.c | |
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/msg.c')
-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: |