return -ECANCELED;
 
                if (!req->result) {
-                       struct poll_table_struct pt = { ._key = poll->events };
+                       struct poll_table_struct pt = { ._key = req->cflags };
 
-                       req->result = vfs_poll(req->file, &pt) & poll->events;
+                       req->result = vfs_poll(req->file, &pt) & req->cflags;
                }
 
                /* multishot, just fill an CQE and proceed */
-               if (req->result && !(poll->events & EPOLLONESHOT)) {
+               if (req->result && !(req->cflags & EPOLLONESHOT)) {
                        __poll_t mask = mangle_poll(req->result & poll->events);
                        bool filled;
 
                io_req_complete_failed(req, ret);
 }
 
-static void __io_poll_execute(struct io_kiocb *req, int mask)
+static void __io_poll_execute(struct io_kiocb *req, int mask, int events)
 {
        req->result = mask;
+       /*
+        * This is useful for poll that is armed on behalf of another
+        * request, and where the wakeup path could be on a different
+        * CPU. We want to avoid pulling in req->apoll->events for that
+        * case.
+        */
+       req->cflags = events;
        if (req->opcode == IORING_OP_POLL_ADD)
                req->io_task_work.func = io_poll_task_func;
        else
        io_req_task_work_add(req, false);
 }
 
-static inline void io_poll_execute(struct io_kiocb *req, int res)
+static inline void io_poll_execute(struct io_kiocb *req, int res, int events)
 {
        if (io_poll_get_ownership(req))
-               __io_poll_execute(req, res);
+               __io_poll_execute(req, res, events);
 }
 
 static void io_poll_cancel_req(struct io_kiocb *req)
 {
        io_poll_mark_cancelled(req);
        /* kick tw, which should complete the request */
-       io_poll_execute(req, 0);
+       io_poll_execute(req, 0, 0);
 }
 
 static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
        if (unlikely(mask & POLLFREE)) {
                io_poll_mark_cancelled(req);
                /* we have to kick tw in case it's not already */
-               io_poll_execute(req, 0);
+               io_poll_execute(req, 0, poll->events);
 
                /*
                 * If the waitqueue is being freed early but someone is already
                        list_del_init(&poll->wait.entry);
                        poll->head = NULL;
                }
-               __io_poll_execute(req, mask);
+               __io_poll_execute(req, mask, poll->events);
        }
        return 1;
 }
                /* can't multishot if failed, just queue the event we've got */
                if (unlikely(ipt->error || !ipt->nr_entries))
                        poll->events |= EPOLLONESHOT;
-               __io_poll_execute(req, mask);
+               __io_poll_execute(req, mask, poll->events);
                return 0;
        }
        io_add_napi(req->file, req->ctx);
         */
        v = atomic_dec_return(&req->poll_refs);
        if (unlikely(v & IO_POLL_REF_MASK))
-               __io_poll_execute(req, 0);
+               __io_poll_execute(req, 0, poll->events);
        return 0;
 }
 
                return -EINVAL;
 
        io_req_set_refcount(req);
-       poll->events = io_poll_parse_events(sqe, flags);
+       req->cflags = poll->events = io_poll_parse_events(sqe, flags);
        return 0;
 }