aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipc/sem.c61
1 files changed, 31 insertions, 30 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 08da8648925d..1b5ae352cde4 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -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
183static 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
189static inline void sem_getref_and_unlock(struct sem_array *sma)
190{
191 ipc_rcu_getref(sma);
192 ipc_unlock(&(sma)->sem_perm);
193}
194
195static 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
183static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) 202static 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);