Messages in this thread Patch in this message | | | Date | Fri, 17 Oct 2008 16:17:40 -0700 (PDT) | From | Davide Libenzi <> | Subject | [patch] epoll avoid double-inserts in case of EFAULT |
| |
First Episode:
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. This patch drops the test done inside the re-insertion loop.
Second Episode:
The test "!ep_is_linked(&epi->rdllink)" wasn't there because we inserts 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 be the reason for the thread "2.6.27-05178-g2e532d6: list_add corruption" from Alexander Beregalov.
Signed-off-by: Davide Libenzi <davidel@xmailserver.org>
- Davide
--- fs/eventpoll.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
Index: linux-2.6.mod/fs/eventpoll.c =================================================================== --- linux-2.6.mod.orig/fs/eventpoll.c 2008-10-17 15:51:09.000000000 -0700 +++ linux-2.6.mod/fs/eventpoll.c 2008-10-17 15:54:14.000000000 -0700 @@ -930,8 +930,15 @@ * 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
| |