|
@@ -962,17 +962,31 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
|
|
|
+static struct sem_undo *__lookup_undo(struct sem_undo_list *ulp, int semid)
|
|
|
{
|
|
|
- struct sem_undo *walk;
|
|
|
+ struct sem_undo *un;
|
|
|
|
|
|
- list_for_each_entry_rcu(walk, &ulp->list_proc, list_proc) {
|
|
|
- if (walk->semid == semid)
|
|
|
- return walk;
|
|
|
+ list_for_each_entry_rcu(un, &ulp->list_proc, list_proc) {
|
|
|
+ if (un->semid == semid)
|
|
|
+ return un;
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
|
|
|
+{
|
|
|
+ struct sem_undo *un;
|
|
|
+
|
|
|
+ assert_spin_locked(&ulp->lock);
|
|
|
+
|
|
|
+ un = __lookup_undo(ulp, semid);
|
|
|
+ if (un) {
|
|
|
+ list_del_rcu(&un->list_proc);
|
|
|
+ list_add_rcu(&un->list_proc, &ulp->list_proc);
|
|
|
+ }
|
|
|
+ return un;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* find_alloc_undo - Lookup (and if not present create) undo array
|
|
|
* @ns: namespace
|
|
@@ -1308,7 +1322,7 @@ void exit_sem(struct task_struct *tsk)
|
|
|
if (IS_ERR(sma))
|
|
|
continue;
|
|
|
|
|
|
- un = lookup_undo(ulp, semid);
|
|
|
+ un = __lookup_undo(ulp, semid);
|
|
|
if (un == NULL) {
|
|
|
/* exit_sem raced with IPC_RMID+semget() that created
|
|
|
* exactly the same semid. Nothing to do.
|