Skip to content

Commit d1bc90d

Browse files
abattersbytorvalds
authored andcommitted
epoll: remove unnecessary xchg
xchg in ep_unregister_pollwait() is unnecessary because it is protected by either epmutex or ep->mtx (the same protection as ep_remove()). If xchg was necessary, it would be insufficient to protect against problems: if multiple concurrent calls to ep_unregister_pollwait() were possible then a second caller that returns without doing anything because nwait == 0 could return before the waitqueues are removed by the first caller, which looks like it could lead to problematic races with ep_poll_callback(). So remove xchg and add comments about the locking. Signed-off-by: Tony Battersby <tonyb@cybernetics.com> Acked-by: Davide Libenzi <davidel@xmailserver.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent d030588 commit d1bc90d

File tree

1 file changed

+8
-14
lines changed

1 file changed

+8
-14
lines changed

fs/eventpoll.c

+8-14
Original file line numberDiff line numberDiff line change
@@ -394,27 +394,21 @@ static void ep_poll_safewake(wait_queue_head_t *wq)
394394
}
395395

396396
/*
397-
* This function unregister poll callbacks from the associated file descriptor.
398-
* Since this must be called without holding "ep->lock" the atomic exchange trick
399-
* will protect us from multiple unregister.
397+
* This function unregisters poll callbacks from the associated file
398+
* descriptor. Must be called with "mtx" held (or "epmutex" if called from
399+
* ep_free).
400400
*/
401401
static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
402402
{
403-
int nwait;
404403
struct list_head *lsthead = &epi->pwqlist;
405404
struct eppoll_entry *pwq;
406405

407-
/* This is called without locks, so we need the atomic exchange */
408-
nwait = xchg(&epi->nwait, 0);
409-
410-
if (nwait) {
411-
while (!list_empty(lsthead)) {
412-
pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
406+
while (!list_empty(lsthead)) {
407+
pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
413408

414-
list_del_init(&pwq->llink);
415-
remove_wait_queue(pwq->whead, &pwq->wait);
416-
kmem_cache_free(pwq_cache, pwq);
417-
}
409+
list_del(&pwq->llink);
410+
remove_wait_queue(pwq->whead, &pwq->wait);
411+
kmem_cache_free(pwq_cache, pwq);
418412
}
419413
}
420414

0 commit comments

Comments
 (0)