diff options
-rw-r--r-- | ipc/sem.c | 61 |
1 files changed, 31 insertions, 30 deletions
@@ -180,6 +180,25 @@ static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns, | |||
180 | return container_of(ipcp, struct sem_array, sem_perm); | 180 | return container_of(ipcp, struct sem_array, sem_perm); |
181 | } | 181 | } |
182 | 182 | ||
183 | static inline void sem_lock_and_putref(struct sem_array *sma) | ||
184 | { | ||
185 | ipc_lock_by_ptr(&sma->sem_perm); | ||
186 | ipc_rcu_putref(sma); | ||
187 | } | ||
188 | |||
189 | static inline void sem_getref_and_unlock(struct sem_array *sma) | ||
190 | { | ||
191 | ipc_rcu_getref(sma); | ||
192 | ipc_unlock(&(sma)->sem_perm); | ||
193 | } | ||
194 | |||
195 | static inline void sem_putref(struct sem_array *sma) | ||
196 | { | ||
197 | ipc_lock_by_ptr(&sma->sem_perm); | ||
198 | ipc_rcu_putref(sma); | ||
199 | ipc_unlock(&(sma)->sem_perm); | ||
200 | } | ||
201 | |||
183 | static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) | 202 | static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) |
184 | { | 203 | { |
185 | ipc_rmid(&sem_ids(ns), &s->sem_perm); | 204 | ipc_rmid(&sem_ids(ns), &s->sem_perm); |
@@ -698,19 +717,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
698 | int i; | 717 | int i; |
699 | 718 | ||
700 | if(nsems > SEMMSL_FAST) { | 719 | if(nsems > SEMMSL_FAST) { |
701 | ipc_rcu_getref(sma); | 720 | sem_getref_and_unlock(sma); |
702 | sem_unlock(sma); | ||
703 | 721 | ||
704 | sem_io = ipc_alloc(sizeof(ushort)*nsems); | 722 | sem_io = ipc_alloc(sizeof(ushort)*nsems); |
705 | if(sem_io == NULL) { | 723 | if(sem_io == NULL) { |
706 | ipc_lock_by_ptr(&sma->sem_perm); | 724 | sem_putref(sma); |
707 | ipc_rcu_putref(sma); | ||
708 | sem_unlock(sma); | ||
709 | return -ENOMEM; | 725 | return -ENOMEM; |
710 | } | 726 | } |
711 | 727 | ||
712 | ipc_lock_by_ptr(&sma->sem_perm); | 728 | sem_lock_and_putref(sma); |
713 | ipc_rcu_putref(sma); | ||
714 | if (sma->sem_perm.deleted) { | 729 | if (sma->sem_perm.deleted) { |
715 | sem_unlock(sma); | 730 | sem_unlock(sma); |
716 | err = -EIDRM; | 731 | err = -EIDRM; |
@@ -731,38 +746,30 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
731 | int i; | 746 | int i; |
732 | struct sem_undo *un; | 747 | struct sem_undo *un; |
733 | 748 | ||
734 | ipc_rcu_getref(sma); | 749 | sem_getref_and_unlock(sma); |
735 | sem_unlock(sma); | ||
736 | 750 | ||
737 | if(nsems > SEMMSL_FAST) { | 751 | if(nsems > SEMMSL_FAST) { |
738 | sem_io = ipc_alloc(sizeof(ushort)*nsems); | 752 | sem_io = ipc_alloc(sizeof(ushort)*nsems); |
739 | if(sem_io == NULL) { | 753 | if(sem_io == NULL) { |
740 | ipc_lock_by_ptr(&sma->sem_perm); | 754 | sem_putref(sma); |
741 | ipc_rcu_putref(sma); | ||
742 | sem_unlock(sma); | ||
743 | return -ENOMEM; | 755 | return -ENOMEM; |
744 | } | 756 | } |
745 | } | 757 | } |
746 | 758 | ||
747 | if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) { | 759 | if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) { |
748 | ipc_lock_by_ptr(&sma->sem_perm); | 760 | sem_putref(sma); |
749 | ipc_rcu_putref(sma); | ||
750 | sem_unlock(sma); | ||
751 | err = -EFAULT; | 761 | err = -EFAULT; |
752 | goto out_free; | 762 | goto out_free; |
753 | } | 763 | } |
754 | 764 | ||
755 | for (i = 0; i < nsems; i++) { | 765 | for (i = 0; i < nsems; i++) { |
756 | if (sem_io[i] > SEMVMX) { | 766 | if (sem_io[i] > SEMVMX) { |
757 | ipc_lock_by_ptr(&sma->sem_perm); | 767 | sem_putref(sma); |
758 | ipc_rcu_putref(sma); | ||
759 | sem_unlock(sma); | ||
760 | err = -ERANGE; | 768 | err = -ERANGE; |
761 | goto out_free; | 769 | goto out_free; |
762 | } | 770 | } |
763 | } | 771 | } |
764 | ipc_lock_by_ptr(&sma->sem_perm); | 772 | sem_lock_and_putref(sma); |
765 | ipc_rcu_putref(sma); | ||
766 | if (sma->sem_perm.deleted) { | 773 | if (sma->sem_perm.deleted) { |
767 | sem_unlock(sma); | 774 | sem_unlock(sma); |
768 | err = -EIDRM; | 775 | err = -EIDRM; |
@@ -1042,14 +1049,11 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid) | |||
1042 | return ERR_PTR(PTR_ERR(sma)); | 1049 | return ERR_PTR(PTR_ERR(sma)); |
1043 | 1050 | ||
1044 | nsems = sma->sem_nsems; | 1051 | nsems = sma->sem_nsems; |
1045 | ipc_rcu_getref(sma); | 1052 | sem_getref_and_unlock(sma); |
1046 | sem_unlock(sma); | ||
1047 | 1053 | ||
1048 | new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL); | 1054 | new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL); |
1049 | if (!new) { | 1055 | if (!new) { |
1050 | ipc_lock_by_ptr(&sma->sem_perm); | 1056 | sem_putref(sma); |
1051 | ipc_rcu_putref(sma); | ||
1052 | sem_unlock(sma); | ||
1053 | return ERR_PTR(-ENOMEM); | 1057 | return ERR_PTR(-ENOMEM); |
1054 | } | 1058 | } |
1055 | new->semadj = (short *) &new[1]; | 1059 | new->semadj = (short *) &new[1]; |
@@ -1060,13 +1064,10 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid) | |||
1060 | if (un) { | 1064 | if (un) { |
1061 | spin_unlock(&ulp->lock); | 1065 | spin_unlock(&ulp->lock); |
1062 | kfree(new); | 1066 | kfree(new); |
1063 | ipc_lock_by_ptr(&sma->sem_perm); | 1067 | sem_putref(sma); |
1064 | ipc_rcu_putref(sma); | ||
1065 | sem_unlock(sma); | ||
1066 | goto out; | 1068 | goto out; |
1067 | } | 1069 | } |
1068 | ipc_lock_by_ptr(&sma->sem_perm); | 1070 | sem_lock_and_putref(sma); |
1069 | ipc_rcu_putref(sma); | ||
1070 | if (sma->sem_perm.deleted) { | 1071 | if (sma->sem_perm.deleted) { |
1071 | sem_unlock(sma); | 1072 | sem_unlock(sma); |
1072 | spin_unlock(&ulp->lock); | 1073 | spin_unlock(&ulp->lock); |