[PATCH 2/6] epoll: avoid double-inserts in case of EFAULT
Paolo Pisati
paolo.pisati at canonical.com
Wed Oct 26 15:26:01 UTC 2011
From: Davide Libenzi <davidel at xmailserver.org>
In commit f337b9c58332bdecde965b436e47ea4c94d30da0 ("epoll: drop
unnecessary test") Thomas found that there is an unnecessary (always
true) test in ep_send_events(). The callback never inserts into
->rdllink while the send loop is performed, and also does the
~EP_PRIVATE_BITS test. Given we're holding the mutex during this time,
the conditions tested inside the loop are always true.
HOWEVER.
The test "!ep_is_linked(&epi->rdllink)" wasn't there because we insert
into ->rdllink, but because the send-events loop might terminate before
the whole list is scanned (-EFAULT).
In such cases, when the loop terminates early, and when a (leftover)
file received an event while we're performing the lockless loop, we need
such test to avoid to double insert the epoll items. The list_splice()
done a few steps below, will correctly re-insert the ones that were left
on "txlist".
This should fix the kenrel.org bugzilla entry 11831.
Signed-off-by: Davide Libenzi <davidel at xmailserver.org>
Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
(cherry picked from commit 9ce209d64d820a6d5ed6b952e2c0f917faad6031)
Signed-off-by: Paolo Pisati <paolo.pisati at canonical.com>
---
fs/eventpoll.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 0e73172..d86c0c9 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -953,8 +953,15 @@ errxit:
* inside the main ready-list here.
*/
for (nepi = ep->ovflist; (epi = nepi) != NULL;
- nepi = epi->next, epi->next = EP_UNACTIVE_PTR)
- list_add_tail(&epi->rdllink, &ep->rdllist);
+ nepi = epi->next, epi->next = EP_UNACTIVE_PTR) {
+ /*
+ * If the above loop quit with errors, the epoll item might still
+ * be linked to "txlist", and the list_splice() done below will
+ * take care of those cases.
+ */
+ if (!ep_is_linked(&epi->rdllink))
+ list_add_tail(&epi->rdllink, &ep->rdllist);
+ }
/*
* We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after
* releasing the lock, events will be queued in the normal way inside
--
1.7.5.4
More information about the kernel-team
mailing list