diff options
Diffstat (limited to 'ipc/sem.c')
-rw-r--r-- | ipc/sem.c | 19 |
1 files changed, 17 insertions, 2 deletions
@@ -264,7 +264,6 @@ static inline void sem_unlock(struct sem_array *sma, int locknum) | |||
264 | struct sem *sem = sma->sem_base + locknum; | 264 | struct sem *sem = sma->sem_base + locknum; |
265 | spin_unlock(&sem->lock); | 265 | spin_unlock(&sem->lock); |
266 | } | 266 | } |
267 | rcu_read_unlock(); | ||
268 | } | 267 | } |
269 | 268 | ||
270 | /* | 269 | /* |
@@ -332,6 +331,7 @@ static inline void sem_putref(struct sem_array *sma) | |||
332 | { | 331 | { |
333 | sem_lock_and_putref(sma); | 332 | sem_lock_and_putref(sma); |
334 | sem_unlock(sma, -1); | 333 | sem_unlock(sma, -1); |
334 | rcu_read_unlock(); | ||
335 | } | 335 | } |
336 | 336 | ||
337 | static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) | 337 | static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) |
@@ -435,6 +435,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) | |||
435 | sma->sem_nsems = nsems; | 435 | sma->sem_nsems = nsems; |
436 | sma->sem_ctime = get_seconds(); | 436 | sma->sem_ctime = get_seconds(); |
437 | sem_unlock(sma, -1); | 437 | sem_unlock(sma, -1); |
438 | rcu_read_unlock(); | ||
438 | 439 | ||
439 | return sma->sem_perm.id; | 440 | return sma->sem_perm.id; |
440 | } | 441 | } |
@@ -874,6 +875,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | |||
874 | /* Remove the semaphore set from the IDR */ | 875 | /* Remove the semaphore set from the IDR */ |
875 | sem_rmid(ns, sma); | 876 | sem_rmid(ns, sma); |
876 | sem_unlock(sma, -1); | 877 | sem_unlock(sma, -1); |
878 | rcu_read_unlock(); | ||
877 | 879 | ||
878 | wake_up_sem_queue_do(&tasks); | 880 | wake_up_sem_queue_do(&tasks); |
879 | ns->used_sems -= sma->sem_nsems; | 881 | ns->used_sems -= sma->sem_nsems; |
@@ -1055,6 +1057,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, | |||
1055 | /* maybe some queued-up processes were waiting for this */ | 1057 | /* maybe some queued-up processes were waiting for this */ |
1056 | do_smart_update(sma, NULL, 0, 0, &tasks); | 1058 | do_smart_update(sma, NULL, 0, 0, &tasks); |
1057 | sem_unlock(sma, -1); | 1059 | sem_unlock(sma, -1); |
1060 | rcu_read_unlock(); | ||
1058 | wake_up_sem_queue_do(&tasks); | 1061 | wake_up_sem_queue_do(&tasks); |
1059 | return 0; | 1062 | return 0; |
1060 | } | 1063 | } |
@@ -1104,10 +1107,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
1104 | if(nsems > SEMMSL_FAST) { | 1107 | if(nsems > SEMMSL_FAST) { |
1105 | if (!ipc_rcu_getref(sma)) { | 1108 | if (!ipc_rcu_getref(sma)) { |
1106 | sem_unlock(sma, -1); | 1109 | sem_unlock(sma, -1); |
1110 | rcu_read_unlock(); | ||
1107 | err = -EIDRM; | 1111 | err = -EIDRM; |
1108 | goto out_free; | 1112 | goto out_free; |
1109 | } | 1113 | } |
1110 | sem_unlock(sma, -1); | 1114 | sem_unlock(sma, -1); |
1115 | rcu_read_unlock(); | ||
1111 | sem_io = ipc_alloc(sizeof(ushort)*nsems); | 1116 | sem_io = ipc_alloc(sizeof(ushort)*nsems); |
1112 | if(sem_io == NULL) { | 1117 | if(sem_io == NULL) { |
1113 | sem_putref(sma); | 1118 | sem_putref(sma); |
@@ -1117,6 +1122,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
1117 | sem_lock_and_putref(sma); | 1122 | sem_lock_and_putref(sma); |
1118 | if (sma->sem_perm.deleted) { | 1123 | if (sma->sem_perm.deleted) { |
1119 | sem_unlock(sma, -1); | 1124 | sem_unlock(sma, -1); |
1125 | rcu_read_unlock(); | ||
1120 | err = -EIDRM; | 1126 | err = -EIDRM; |
1121 | goto out_free; | 1127 | goto out_free; |
1122 | } | 1128 | } |
@@ -1124,6 +1130,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
1124 | for (i = 0; i < sma->sem_nsems; i++) | 1130 | for (i = 0; i < sma->sem_nsems; i++) |
1125 | sem_io[i] = sma->sem_base[i].semval; | 1131 | sem_io[i] = sma->sem_base[i].semval; |
1126 | sem_unlock(sma, -1); | 1132 | sem_unlock(sma, -1); |
1133 | rcu_read_unlock(); | ||
1127 | err = 0; | 1134 | err = 0; |
1128 | if(copy_to_user(array, sem_io, nsems*sizeof(ushort))) | 1135 | if(copy_to_user(array, sem_io, nsems*sizeof(ushort))) |
1129 | err = -EFAULT; | 1136 | err = -EFAULT; |
@@ -1164,6 +1171,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
1164 | sem_lock_and_putref(sma); | 1171 | sem_lock_and_putref(sma); |
1165 | if (sma->sem_perm.deleted) { | 1172 | if (sma->sem_perm.deleted) { |
1166 | sem_unlock(sma, -1); | 1173 | sem_unlock(sma, -1); |
1174 | rcu_read_unlock(); | ||
1167 | err = -EIDRM; | 1175 | err = -EIDRM; |
1168 | goto out_free; | 1176 | goto out_free; |
1169 | } | 1177 | } |
@@ -1210,6 +1218,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
1210 | 1218 | ||
1211 | out_unlock: | 1219 | out_unlock: |
1212 | sem_unlock(sma, -1); | 1220 | sem_unlock(sma, -1); |
1221 | rcu_read_unlock(); | ||
1213 | out_wakeup: | 1222 | out_wakeup: |
1214 | wake_up_sem_queue_do(&tasks); | 1223 | wake_up_sem_queue_do(&tasks); |
1215 | out_free: | 1224 | out_free: |
@@ -1295,6 +1304,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid, | |||
1295 | 1304 | ||
1296 | out_unlock: | 1305 | out_unlock: |
1297 | sem_unlock(sma, -1); | 1306 | sem_unlock(sma, -1); |
1307 | rcu_read_unlock(); | ||
1298 | out_up: | 1308 | out_up: |
1299 | up_write(&sem_ids(ns).rw_mutex); | 1309 | up_write(&sem_ids(ns).rw_mutex); |
1300 | return err; | 1310 | return err; |
@@ -1443,9 +1453,11 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) | |||
1443 | } | 1453 | } |
1444 | 1454 | ||
1445 | /* step 3: Acquire the lock on semaphore array */ | 1455 | /* step 3: Acquire the lock on semaphore array */ |
1456 | /* This also does the rcu_read_lock() */ | ||
1446 | sem_lock_and_putref(sma); | 1457 | sem_lock_and_putref(sma); |
1447 | if (sma->sem_perm.deleted) { | 1458 | if (sma->sem_perm.deleted) { |
1448 | sem_unlock(sma, -1); | 1459 | sem_unlock(sma, -1); |
1460 | rcu_read_unlock(); | ||
1449 | kfree(new); | 1461 | kfree(new); |
1450 | un = ERR_PTR(-EIDRM); | 1462 | un = ERR_PTR(-EIDRM); |
1451 | goto out; | 1463 | goto out; |
@@ -1472,7 +1484,6 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) | |||
1472 | 1484 | ||
1473 | success: | 1485 | success: |
1474 | spin_unlock(&ulp->lock); | 1486 | spin_unlock(&ulp->lock); |
1475 | rcu_read_lock(); | ||
1476 | sem_unlock(sma, -1); | 1487 | sem_unlock(sma, -1); |
1477 | out: | 1488 | out: |
1478 | return un; | 1489 | return un; |
@@ -1648,6 +1659,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, | |||
1648 | sleep_again: | 1659 | sleep_again: |
1649 | current->state = TASK_INTERRUPTIBLE; | 1660 | current->state = TASK_INTERRUPTIBLE; |
1650 | sem_unlock(sma, locknum); | 1661 | sem_unlock(sma, locknum); |
1662 | rcu_read_unlock(); | ||
1651 | 1663 | ||
1652 | if (timeout) | 1664 | if (timeout) |
1653 | jiffies_left = schedule_timeout(jiffies_left); | 1665 | jiffies_left = schedule_timeout(jiffies_left); |
@@ -1709,6 +1721,7 @@ sleep_again: | |||
1709 | 1721 | ||
1710 | out_unlock_free: | 1722 | out_unlock_free: |
1711 | sem_unlock(sma, locknum); | 1723 | sem_unlock(sma, locknum); |
1724 | rcu_read_unlock(); | ||
1712 | out_wakeup: | 1725 | out_wakeup: |
1713 | wake_up_sem_queue_do(&tasks); | 1726 | wake_up_sem_queue_do(&tasks); |
1714 | out_free: | 1727 | out_free: |
@@ -1801,6 +1814,7 @@ void exit_sem(struct task_struct *tsk) | |||
1801 | * exactly the same semid. Nothing to do. | 1814 | * exactly the same semid. Nothing to do. |
1802 | */ | 1815 | */ |
1803 | sem_unlock(sma, -1); | 1816 | sem_unlock(sma, -1); |
1817 | rcu_read_unlock(); | ||
1804 | continue; | 1818 | continue; |
1805 | } | 1819 | } |
1806 | 1820 | ||
@@ -1841,6 +1855,7 @@ void exit_sem(struct task_struct *tsk) | |||
1841 | INIT_LIST_HEAD(&tasks); | 1855 | INIT_LIST_HEAD(&tasks); |
1842 | do_smart_update(sma, NULL, 0, 1, &tasks); | 1856 | do_smart_update(sma, NULL, 0, 1, &tasks); |
1843 | sem_unlock(sma, -1); | 1857 | sem_unlock(sma, -1); |
1858 | rcu_read_unlock(); | ||
1844 | wake_up_sem_queue_do(&tasks); | 1859 | wake_up_sem_queue_do(&tasks); |
1845 | 1860 | ||
1846 | kfree_rcu(un, rcu); | 1861 | kfree_rcu(un, rcu); |