diff options
author | Davidlohr Bueso <davidlohr.bueso@hp.com> | 2013-09-11 17:26:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:59:39 -0400 |
commit | 79ccf0f8c8e04e8b9eda6645ba0f63b0915a3075 (patch) | |
tree | 7178c7dbb1edd12689359f49da36d4e04de93cf8 /ipc | |
parent | 8b8d52ac382b17a19906b930cd69e2edb0aca8ba (diff) |
ipc,shm: shorten critical region in shmctl_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>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Manfred Spraul <manfred@colorfullife.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/shm.c | 10 |
1 files changed, 6 insertions, 4 deletions
@@ -780,11 +780,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, | |||
780 | down_write(&shm_ids(ns).rw_mutex); | 780 | down_write(&shm_ids(ns).rw_mutex); |
781 | rcu_read_lock(); | 781 | rcu_read_lock(); |
782 | 782 | ||
783 | ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd, | 783 | ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd, |
784 | &shmid64.shm_perm, 0); | 784 | &shmid64.shm_perm, 0); |
785 | if (IS_ERR(ipcp)) { | 785 | if (IS_ERR(ipcp)) { |
786 | err = PTR_ERR(ipcp); | 786 | err = PTR_ERR(ipcp); |
787 | /* the ipc lock is not held upon failure */ | ||
788 | goto out_unlock1; | 787 | goto out_unlock1; |
789 | } | 788 | } |
790 | 789 | ||
@@ -792,14 +791,16 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, | |||
792 | 791 | ||
793 | err = security_shm_shmctl(shp, cmd); | 792 | err = security_shm_shmctl(shp, cmd); |
794 | if (err) | 793 | if (err) |
795 | goto out_unlock0; | 794 | goto out_unlock1; |
796 | 795 | ||
797 | switch (cmd) { | 796 | switch (cmd) { |
798 | case IPC_RMID: | 797 | case IPC_RMID: |
798 | ipc_lock_object(&shp->shm_perm); | ||
799 | /* do_shm_rmid unlocks the ipc object and rcu */ | 799 | /* do_shm_rmid unlocks the ipc object and rcu */ |
800 | do_shm_rmid(ns, ipcp); | 800 | do_shm_rmid(ns, ipcp); |
801 | goto out_up; | 801 | goto out_up; |
802 | case IPC_SET: | 802 | case IPC_SET: |
803 | ipc_lock_object(&shp->shm_perm); | ||
803 | err = ipc_update_perm(&shmid64.shm_perm, ipcp); | 804 | err = ipc_update_perm(&shmid64.shm_perm, ipcp); |
804 | if (err) | 805 | if (err) |
805 | goto out_unlock0; | 806 | goto out_unlock0; |
@@ -807,6 +808,7 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, | |||
807 | break; | 808 | break; |
808 | default: | 809 | default: |
809 | err = -EINVAL; | 810 | err = -EINVAL; |
811 | goto out_unlock1; | ||
810 | } | 812 | } |
811 | 813 | ||
812 | out_unlock0: | 814 | out_unlock0: |