aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/eventpoll.c30
-rw-r--r--fs/signalfd.c6
2 files changed, 32 insertions, 4 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 34bbfc6dd8dc..ea54cdef04dd 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -320,6 +320,11 @@ static inline int ep_is_linked(struct list_head *p)
320 return !list_empty(p); 320 return !list_empty(p);
321} 321}
322 322
323static inline struct eppoll_entry *ep_pwq_from_wait(wait_queue_t *p)
324{
325 return container_of(p, struct eppoll_entry, wait);
326}
327
323/* Get the "struct epitem" from a wait queue pointer */ 328/* Get the "struct epitem" from a wait queue pointer */
324static inline struct epitem *ep_item_from_wait(wait_queue_t *p) 329static inline struct epitem *ep_item_from_wait(wait_queue_t *p)
325{ 330{
@@ -467,6 +472,18 @@ static void ep_poll_safewake(wait_queue_head_t *wq)
467 put_cpu(); 472 put_cpu();
468} 473}
469 474
475static void ep_remove_wait_queue(struct eppoll_entry *pwq)
476{
477 wait_queue_head_t *whead;
478
479 rcu_read_lock();
480 /* If it is cleared by POLLFREE, it should be rcu-safe */
481 whead = rcu_dereference(pwq->whead);
482 if (whead)
483 remove_wait_queue(whead, &pwq->wait);
484 rcu_read_unlock();
485}
486
470/* 487/*
471 * This function unregisters poll callbacks from the associated file 488 * This function unregisters poll callbacks from the associated file
472 * descriptor. Must be called with "mtx" held (or "epmutex" if called from 489 * descriptor. Must be called with "mtx" held (or "epmutex" if called from
@@ -481,7 +498,7 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
481 pwq = list_first_entry(lsthead, struct eppoll_entry, llink); 498 pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
482 499
483 list_del(&pwq->llink); 500 list_del(&pwq->llink);
484 remove_wait_queue(pwq->whead, &pwq->wait); 501 ep_remove_wait_queue(pwq);
485 kmem_cache_free(pwq_cache, pwq); 502 kmem_cache_free(pwq_cache, pwq);
486 } 503 }
487} 504}
@@ -842,9 +859,16 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
842 struct epitem *epi = ep_item_from_wait(wait); 859 struct epitem *epi = ep_item_from_wait(wait);
843 struct eventpoll *ep = epi->ep; 860 struct eventpoll *ep = epi->ep;
844 861
845 /* the caller holds eppoll_entry->whead->lock */ 862 if ((unsigned long)key & POLLFREE) {
846 if ((unsigned long)key & POLLFREE) 863 ep_pwq_from_wait(wait)->whead = NULL;
864 /*
865 * whead = NULL above can race with ep_remove_wait_queue()
866 * which can do another remove_wait_queue() after us, so we
867 * can't use __remove_wait_queue(). whead->lock is held by
868 * the caller.
869 */
847 list_del_init(&wait->task_list); 870 list_del_init(&wait->task_list);
871 }
848 872
849 spin_lock_irqsave(&ep->lock, flags); 873 spin_lock_irqsave(&ep->lock, flags);
850 874
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 79c1eea98a3a..7ae2a574cb25 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -33,7 +33,11 @@
33void signalfd_cleanup(struct sighand_struct *sighand) 33void signalfd_cleanup(struct sighand_struct *sighand)
34{ 34{
35 wait_queue_head_t *wqh = &sighand->signalfd_wqh; 35 wait_queue_head_t *wqh = &sighand->signalfd_wqh;
36 36 /*
37 * The lockless check can race with remove_wait_queue() in progress,
38 * but in this case its caller should run under rcu_read_lock() and
39 * sighand_cachep is SLAB_DESTROY_BY_RCU, we can safely return.
40 */
37 if (likely(!waitqueue_active(wqh))) 41 if (likely(!waitqueue_active(wqh)))
38 return; 42 return;
39 43