eventpoll: fix missing wakeup for ovflist in ep_poll_callback
In the event that we add to ovflist, before commit339ddb53d3("fs/epoll: remove unnecessary wakeups of nested epoll") we would be woken up by ep_scan_ready_list, and did no wakeup in ep_poll_callback. With that wakeup removed, if we add to ovflist here, we may never wake up. Rather than adding back the ep_scan_ready_list wakeup - which was resulting in unnecessary wakeups, trigger a wake-up in ep_poll_callback. We noticed that one of our workloads was missing wakeups starting with339ddb53d3and upon manual inspection, this wakeup seemed missing to me. With this patch added, we no longer see missing wakeups. I haven't yet tried to make a small reproducer, but the existing kselftests in filesystem/epoll passed for me with this patch. [khazhy@google.com: use if/elif instead of goto + cleanup suggested by Roman] Link: http://lkml.kernel.org/r/20200424190039.192373-1-khazhy@google.com Fixes:339ddb53d3("fs/epoll: remove unnecessary wakeups of nested epoll") Signed-off-by: Khazhismel Kumykov <khazhy@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Roman Penyaev <rpenyaev@suse.de> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Roman Penyaev <rpenyaev@suse.de> Cc: Heiher <r@hev.cc> Cc: Jason Baron <jbaron@akamai.com> Cc: <stable@vger.kernel.org> Link: http://lkml.kernel.org/r/20200424025057.118641-1-khazhy@google.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
996ed22c7a
commit
0c54a6a44b
|
|
@ -1171,6 +1171,10 @@ static inline bool chain_epi_lockless(struct epitem *epi)
|
|||
{
|
||||
struct eventpoll *ep = epi->ep;
|
||||
|
||||
/* Fast preliminary check */
|
||||
if (epi->next != EP_UNACTIVE_PTR)
|
||||
return false;
|
||||
|
||||
/* Check that the same epi has not been just chained from another CPU */
|
||||
if (cmpxchg(&epi->next, EP_UNACTIVE_PTR, NULL) != EP_UNACTIVE_PTR)
|
||||
return false;
|
||||
|
|
@ -1237,16 +1241,12 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
|
|||
* chained in ep->ovflist and requeued later on.
|
||||
*/
|
||||
if (READ_ONCE(ep->ovflist) != EP_UNACTIVE_PTR) {
|
||||
if (epi->next == EP_UNACTIVE_PTR &&
|
||||
chain_epi_lockless(epi))
|
||||
if (chain_epi_lockless(epi))
|
||||
ep_pm_stay_awake_rcu(epi);
|
||||
} else if (!ep_is_linked(epi)) {
|
||||
/* In the usual case, add event to ready list. */
|
||||
if (list_add_tail_lockless(&epi->rdllink, &ep->rdllist))
|
||||
ep_pm_stay_awake_rcu(epi);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* If this file is already in the ready list we exit soon */
|
||||
if (!ep_is_linked(epi) &&
|
||||
list_add_tail_lockless(&epi->rdllink, &ep->rdllist)) {
|
||||
ep_pm_stay_awake_rcu(epi);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue