diff options
| author | Pierre Peiffer <pierre.peiffer@bull.net> | 2008-04-29 04:00:49 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 11:06:13 -0400 |
| commit | 522bb2a2b420a0c1d0fcd037aa4e1bb9e2bca447 (patch) | |
| tree | 6023efd860b807e7d50a20eebeaebe3e21d0285b /ipc | |
| parent | a0d092fc2df845a43cc4847836818f49331d0a5c (diff) | |
IPC/semaphores: move the rwmutex handling inside semctl_down
semctl_down is called with the rwmutex (the one which protects the list of
ipcs) taken in write mode.
This patch moves this rwmutex taken in write-mode inside semctl_down.
This has the advantages of reducing a little bit the window during which this
rwmutex is taken, clarifying sys_semctl, and finally of having a coherent
behaviour with [shm|msg]ctl_down
Signed-off-by: Pierre Peiffer <pierre.peiffer@bull.net>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Cc: Nadia Derbey <Nadia.Derbey@bull.net>
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/sem.c | 24 |
1 files changed, 13 insertions, 11 deletions
| @@ -875,6 +875,11 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __ | |||
| 875 | } | 875 | } |
| 876 | } | 876 | } |
| 877 | 877 | ||
| 878 | /* | ||
| 879 | * This function handles some semctl commands which require the rw_mutex | ||
| 880 | * to be held in write mode. | ||
| 881 | * NOTE: no locks must be held, the rw_mutex is taken inside this function. | ||
| 882 | */ | ||
| 878 | static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, | 883 | static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, |
| 879 | int cmd, int version, union semun arg) | 884 | int cmd, int version, union semun arg) |
| 880 | { | 885 | { |
| @@ -887,9 +892,12 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, | |||
| 887 | if(copy_semid_from_user (&setbuf, arg.buf, version)) | 892 | if(copy_semid_from_user (&setbuf, arg.buf, version)) |
| 888 | return -EFAULT; | 893 | return -EFAULT; |
| 889 | } | 894 | } |
| 895 | down_write(&sem_ids(ns).rw_mutex); | ||
| 890 | sma = sem_lock_check_down(ns, semid); | 896 | sma = sem_lock_check_down(ns, semid); |
| 891 | if (IS_ERR(sma)) | 897 | if (IS_ERR(sma)) { |
| 892 | return PTR_ERR(sma); | 898 | err = PTR_ERR(sma); |
| 899 | goto out_up; | ||
| 900 | } | ||
| 893 | 901 | ||
| 894 | ipcp = &sma->sem_perm; | 902 | ipcp = &sma->sem_perm; |
| 895 | 903 | ||
| @@ -915,26 +923,22 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, | |||
| 915 | switch(cmd){ | 923 | switch(cmd){ |
| 916 | case IPC_RMID: | 924 | case IPC_RMID: |
| 917 | freeary(ns, ipcp); | 925 | freeary(ns, ipcp); |
| 918 | err = 0; | 926 | goto out_up; |
| 919 | break; | ||
| 920 | case IPC_SET: | 927 | case IPC_SET: |
| 921 | ipcp->uid = setbuf.uid; | 928 | ipcp->uid = setbuf.uid; |
| 922 | ipcp->gid = setbuf.gid; | 929 | ipcp->gid = setbuf.gid; |
| 923 | ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | 930 | ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
| 924 | | (setbuf.mode & S_IRWXUGO); | 931 | | (setbuf.mode & S_IRWXUGO); |
| 925 | sma->sem_ctime = get_seconds(); | 932 | sma->sem_ctime = get_seconds(); |
| 926 | sem_unlock(sma); | ||
| 927 | err = 0; | ||
| 928 | break; | 933 | break; |
| 929 | default: | 934 | default: |
| 930 | sem_unlock(sma); | ||
| 931 | err = -EINVAL; | 935 | err = -EINVAL; |
| 932 | break; | ||
| 933 | } | 936 | } |
| 934 | return err; | ||
| 935 | 937 | ||
| 936 | out_unlock: | 938 | out_unlock: |
| 937 | sem_unlock(sma); | 939 | sem_unlock(sma); |
| 940 | out_up: | ||
| 941 | up_write(&sem_ids(ns).rw_mutex); | ||
| 938 | return err; | 942 | return err; |
| 939 | } | 943 | } |
| 940 | 944 | ||
| @@ -968,9 +972,7 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | |||
| 968 | return err; | 972 | return err; |
| 969 | case IPC_RMID: | 973 | case IPC_RMID: |
| 970 | case IPC_SET: | 974 | case IPC_SET: |
| 971 | down_write(&sem_ids(ns).rw_mutex); | ||
| 972 | err = semctl_down(ns,semid,semnum,cmd,version,arg); | 975 | err = semctl_down(ns,semid,semnum,cmd,version,arg); |
| 973 | up_write(&sem_ids(ns).rw_mutex); | ||
| 974 | return err; | 976 | return err; |
| 975 | default: | 977 | default: |
| 976 | return -EINVAL; | 978 | return -EINVAL; |
