diff options
Diffstat (limited to 'ipc/sem.c')
-rw-r--r-- | ipc/sem.c | 16 |
1 files changed, 7 insertions, 9 deletions
@@ -269,6 +269,8 @@ static inline void sem_unlock(struct sem_array *sma, int locknum) | |||
269 | /* | 269 | /* |
270 | * sem_lock_(check_) routines are called in the paths where the rw_mutex | 270 | * sem_lock_(check_) routines are called in the paths where the rw_mutex |
271 | * is not held. | 271 | * is not held. |
272 | * | ||
273 | * The caller holds the RCU read lock. | ||
272 | */ | 274 | */ |
273 | static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, | 275 | static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, |
274 | int id, struct sembuf *sops, int nsops, int *locknum) | 276 | int id, struct sembuf *sops, int nsops, int *locknum) |
@@ -276,12 +278,9 @@ static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, | |||
276 | struct kern_ipc_perm *ipcp; | 278 | struct kern_ipc_perm *ipcp; |
277 | struct sem_array *sma; | 279 | struct sem_array *sma; |
278 | 280 | ||
279 | rcu_read_lock(); | ||
280 | ipcp = ipc_obtain_object(&sem_ids(ns), id); | 281 | ipcp = ipc_obtain_object(&sem_ids(ns), id); |
281 | if (IS_ERR(ipcp)) { | 282 | if (IS_ERR(ipcp)) |
282 | sma = ERR_CAST(ipcp); | 283 | return ERR_CAST(ipcp); |
283 | goto err; | ||
284 | } | ||
285 | 284 | ||
286 | sma = container_of(ipcp, struct sem_array, sem_perm); | 285 | sma = container_of(ipcp, struct sem_array, sem_perm); |
287 | *locknum = sem_lock(sma, sops, nsops); | 286 | *locknum = sem_lock(sma, sops, nsops); |
@@ -293,10 +292,7 @@ static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, | |||
293 | return container_of(ipcp, struct sem_array, sem_perm); | 292 | return container_of(ipcp, struct sem_array, sem_perm); |
294 | 293 | ||
295 | sem_unlock(sma, *locknum); | 294 | sem_unlock(sma, *locknum); |
296 | sma = ERR_PTR(-EINVAL); | 295 | return ERR_PTR(-EINVAL); |
297 | err: | ||
298 | rcu_read_unlock(); | ||
299 | return sma; | ||
300 | } | 296 | } |
301 | 297 | ||
302 | static inline struct sem_array *sem_obtain_object(struct ipc_namespace *ns, int id) | 298 | static inline struct sem_array *sem_obtain_object(struct ipc_namespace *ns, int id) |
@@ -1680,6 +1676,7 @@ sleep_again: | |||
1680 | goto out_free; | 1676 | goto out_free; |
1681 | } | 1677 | } |
1682 | 1678 | ||
1679 | rcu_read_lock(); | ||
1683 | sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum); | 1680 | sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum); |
1684 | 1681 | ||
1685 | /* | 1682 | /* |
@@ -1691,6 +1688,7 @@ sleep_again: | |||
1691 | * Array removed? If yes, leave without sem_unlock(). | 1688 | * Array removed? If yes, leave without sem_unlock(). |
1692 | */ | 1689 | */ |
1693 | if (IS_ERR(sma)) { | 1690 | if (IS_ERR(sma)) { |
1691 | rcu_read_unlock(); | ||
1694 | goto out_free; | 1692 | goto out_free; |
1695 | } | 1693 | } |
1696 | 1694 | ||