aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavide Libenzi <davidel@xmailserver.org>2008-10-17 19:17:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-26 15:09:49 -0400
commit9ce209d64d820a6d5ed6b952e2c0f917faad6031 (patch)
tree817c5bd01e6666c8269d29d3d8292b5e75ea7fb3 /fs
parent4d36a9e65d4966b433b2f3424d9457468bc80e00 (diff)
epoll: avoid double-inserts in case of EFAULT
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@xmailserver.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/eventpoll.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 99368bda026..aec5c13f634 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -930,8 +930,15 @@ errxit:
930 * inside the main ready-list here. 930 * inside the main ready-list here.
931 */ 931 */
932 for (nepi = ep->ovflist; (epi = nepi) != NULL; 932 for (nepi = ep->ovflist; (epi = nepi) != NULL;
933 nepi = epi->next, epi->next = EP_UNACTIVE_PTR) 933 nepi = epi->next, epi->next = EP_UNACTIVE_PTR) {
934 list_add_tail(&epi->rdllink, &ep->rdllist); 934 /*
935 * If the above loop quit with errors, the epoll item might still
936 * be linked to "txlist", and the list_splice() done below will
937 * take care of those cases.
938 */
939 if (!ep_is_linked(&epi->rdllink))
940 list_add_tail(&epi->rdllink, &ep->rdllist);
941 }
935 /* 942 /*
936 * We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after 943 * We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after
937 * releasing the lock, events will be queued in the normal way inside 944 * releasing the lock, events will be queued in the normal way inside