diff options
author | Davidlohr Bueso <davidlohr.bueso@hp.com> | 2013-09-11 17:26:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:59:39 -0400 |
commit | 68eccc1dc345539d589ae78ee43b835c1a06a134 (patch) | |
tree | 16943d2674537a5d13a14794763a3df7e51411ab /ipc | |
parent | 3b1c4ad37741e53804ffe0a30dd01e08b2ab6241 (diff) |
ipc,shm: introduce shmctl_nolock
Similar to semctl and msgctl, when calling msgctl, the *_INFO and *_STAT
commands can be performed without acquiring the ipc object.
Add a shmctl_nolock() function and move the logic of *_INFO and *_STAT out
of msgctl(). Since we are just moving functionality, 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>
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 | 57 |
1 files changed, 39 insertions, 18 deletions
@@ -820,29 +820,24 @@ out_up: | |||
820 | return err; | 820 | return err; |
821 | } | 821 | } |
822 | 822 | ||
823 | SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | 823 | static int shmctl_nolock(struct ipc_namespace *ns, int shmid, |
824 | int cmd, int version, void __user *buf) | ||
824 | { | 825 | { |
826 | int err; | ||
825 | struct shmid_kernel *shp; | 827 | struct shmid_kernel *shp; |
826 | int err, version; | ||
827 | struct ipc_namespace *ns; | ||
828 | 828 | ||
829 | if (cmd < 0 || shmid < 0) { | 829 | /* preliminary security checks for *_INFO */ |
830 | err = -EINVAL; | 830 | if (cmd == IPC_INFO || cmd == SHM_INFO) { |
831 | goto out; | 831 | err = security_shm_shmctl(NULL, cmd); |
832 | if (err) | ||
833 | return err; | ||
832 | } | 834 | } |
833 | 835 | ||
834 | version = ipc_parse_version(&cmd); | 836 | switch (cmd) { |
835 | ns = current->nsproxy->ipc_ns; | ||
836 | |||
837 | switch (cmd) { /* replace with proc interface ? */ | ||
838 | case IPC_INFO: | 837 | case IPC_INFO: |
839 | { | 838 | { |
840 | struct shminfo64 shminfo; | 839 | struct shminfo64 shminfo; |
841 | 840 | ||
842 | err = security_shm_shmctl(NULL, cmd); | ||
843 | if (err) | ||
844 | return err; | ||
845 | |||
846 | memset(&shminfo, 0, sizeof(shminfo)); | 841 | memset(&shminfo, 0, sizeof(shminfo)); |
847 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; | 842 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; |
848 | shminfo.shmmax = ns->shm_ctlmax; | 843 | shminfo.shmmax = ns->shm_ctlmax; |
@@ -864,10 +859,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | |||
864 | { | 859 | { |
865 | struct shm_info shm_info; | 860 | struct shm_info shm_info; |
866 | 861 | ||
867 | err = security_shm_shmctl(NULL, cmd); | ||
868 | if (err) | ||
869 | return err; | ||
870 | |||
871 | memset(&shm_info, 0, sizeof(shm_info)); | 862 | memset(&shm_info, 0, sizeof(shm_info)); |
872 | down_read(&shm_ids(ns).rw_mutex); | 863 | down_read(&shm_ids(ns).rw_mutex); |
873 | shm_info.used_ids = shm_ids(ns).in_use; | 864 | shm_info.used_ids = shm_ids(ns).in_use; |
@@ -928,6 +919,36 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | |||
928 | err = result; | 919 | err = result; |
929 | goto out; | 920 | goto out; |
930 | } | 921 | } |
922 | default: | ||
923 | return -EINVAL; | ||
924 | } | ||
925 | |||
926 | out_unlock: | ||
927 | shm_unlock(shp); | ||
928 | out: | ||
929 | return err; | ||
930 | } | ||
931 | |||
932 | SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
933 | { | ||
934 | struct shmid_kernel *shp; | ||
935 | int err, version; | ||
936 | struct ipc_namespace *ns; | ||
937 | |||
938 | if (cmd < 0 || shmid < 0) { | ||
939 | err = -EINVAL; | ||
940 | goto out; | ||
941 | } | ||
942 | |||
943 | version = ipc_parse_version(&cmd); | ||
944 | ns = current->nsproxy->ipc_ns; | ||
945 | |||
946 | switch (cmd) { | ||
947 | case IPC_INFO: | ||
948 | case SHM_INFO: | ||
949 | case SHM_STAT: | ||
950 | case IPC_STAT: | ||
951 | return shmctl_nolock(ns, shmid, cmd, version, buf); | ||
931 | case SHM_LOCK: | 952 | case SHM_LOCK: |
932 | case SHM_UNLOCK: | 953 | case SHM_UNLOCK: |
933 | { | 954 | { |