summaryrefslogtreecommitdiff
path: root/fs/eventpoll.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2020-09-27 11:03:32 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2020-10-25 20:02:05 -0400
commitd1ec50adb560983635bd31263012e688cc167f31 (patch)
tree1dd3a968b2ffbd59b94b62d873eda7019ac16bca /fs/eventpoll.c
parent2c0b71c1e9c9362c9503f218fed62aeb66a2ef97 (diff)
ep_insert(): move creation of wakeup source past the fl_ep_links insertion
That's the beginning of preparations for taking f_ep_links out of struct file. If insertion might fail, we will need a new failure exit. Having wakeup source creation done after that point will simplify life there; ep_remove() can (and commonly does) live with NULL epi->ws, so it can be used for cleanup after ep_create_wakeup_source() failure. It can't be used before the rbtree insertion, though, so if we are to unify all old failure exits, we need to move that thing down. Then we would be free to do simple kmem_cache_free() on the failure to insert into f_ep_links - no wakeup source to leak on that failure exit. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/eventpoll.c')
-rw-r--r--fs/eventpoll.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 4903104137c6..680f4ada53d4 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1356,26 +1356,16 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
user_watches = atomic_long_read(&ep->user->epoll_watches);
if (unlikely(user_watches >= max_user_watches))
return -ENOSPC;
- if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL)))
+ if (!(epi = kmem_cache_zalloc(epi_cache, GFP_KERNEL)))
return -ENOMEM;
/* Item initialization follow here ... */
INIT_LIST_HEAD(&epi->rdllink);
INIT_LIST_HEAD(&epi->fllink);
- epi->pwqlist = NULL;
epi->ep = ep;
ep_set_ffd(&epi->ffd, tfile, fd);
epi->event = *event;
epi->next = EP_UNACTIVE_PTR;
- if (epi->event.events & EPOLLWAKEUP) {
- error = ep_create_wakeup_source(epi);
- if (error) {
- kmem_cache_free(epi_cache, epi);
- return error;
- }
- } else {
- RCU_INIT_POINTER(epi->ws, NULL);
- }
atomic_long_inc(&ep->user->epoll_watches);
@@ -1400,6 +1390,14 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
return -EINVAL;
}
+ if (epi->event.events & EPOLLWAKEUP) {
+ error = ep_create_wakeup_source(epi);
+ if (error) {
+ ep_remove(ep, epi);
+ return error;
+ }
+ }
+
/* Initialize the poll table using the queue callback */
epq.epi = epi;
init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);