Commit 03a7beb5 authored by Paton J. Lewis's avatar Paton J. Lewis Committed by Linus Torvalds

epoll: support for disabling items, and a self-test app

Enhanced epoll_ctl to support EPOLL_CTL_DISABLE, which disables an epoll
item.  If epoll_ctl doesn't return -EBUSY in this case, it is then safe to
delete the epoll item in a multi-threaded environment.  Also added a new
test_epoll self- test app to both demonstrate the need for this feature
and test it.
Signed-off-by: default avatarPaton J. Lewis <>
Cc: Alexander Viro <>
Cc: Jason Baron <>
Cc: Paul Holland <>
Cc: Davide Libenzi <>
Cc: Michael Kerrisk <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
parent a0a0a7a9
......@@ -346,7 +346,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)
/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
static inline int ep_op_has_event(int op)
return op != EPOLL_CTL_DEL;
return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD;
/* Initialize the poll safe wake up structure */
......@@ -676,6 +676,34 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
return 0;
* Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item
* had no event flags set, indicating that another thread may be currently
* handling that item's events (in the case that EPOLLONESHOT was being
* used). Otherwise a zero result indicates that the item has been disabled
* from receiving events. A disabled item may be re-enabled via
* EPOLL_CTL_MOD. Must be called with "mtx" held.
static int ep_disable(struct eventpoll *ep, struct epitem *epi)
int result = 0;
unsigned long flags;
spin_lock_irqsave(&ep->lock, flags);
if (epi-> & ~EP_PRIVATE_BITS) {
if (ep_is_linked(&epi->rdllink))
/* Ensure ep_poll_callback will not add epi back onto ready
list: */
result = -EBUSY;
spin_unlock_irqrestore(&ep->lock, flags);
return result;
static void ep_free(struct eventpoll *ep)
struct rb_node *rbp;
......@@ -1020,8 +1048,6 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
rb_insert_color(&epi->rbn, &ep->rbr);
#define PATH_ARR_SIZE 5
* These are the number paths of length 1 to 5, that we are allowing to emanate
......@@ -1787,6 +1813,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
} else
error = -ENOENT;
if (epi)
error = ep_disable(ep, epi);
error = -ENOENT;
......@@ -25,6 +25,7 @@
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_DEL 2
#define EPOLL_CTL_MOD 3
* Request the handling of system wakeup events so as to prevent system suspends
TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug
TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll
for TARGET in $(TARGETS); do \
# Makefile for epoll selftests
all: test_epoll
%: %.c
gcc -pthread -g -o $@ $^
run_tests: all
$(RM) test_epoll
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment