diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/sem.c | 26 | 
1 files changed, 20 insertions, 6 deletions
| diff --git a/ipc/sem.c b/ipc/sem.c index 2f2a47959576..cb0070ecf5bf 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -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. |