| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968 |
- // SPDX-License-Identifier: GPL-2.0
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/fs.h>
- #include <linux/file.h>
- #include <linux/mm.h>
- #include <linux/slab.h>
- #include <linux/poll.h>
- #include <linux/hashtable.h>
- #include <linux/io_uring.h>
- #include <trace/events/io_uring.h>
- #include <uapi/linux/io_uring.h>
- #include "io_uring.h"
- #include "alloc_cache.h"
- #include "refs.h"
- #include "napi.h"
- #include "opdef.h"
- #include "kbuf.h"
- #include "poll.h"
- #include "cancel.h"
- struct io_poll_update {
- struct file *file;
- u64 old_user_data;
- u64 new_user_data;
- __poll_t events;
- bool update_events;
- bool update_user_data;
- };
- struct io_poll_table {
- struct poll_table_struct pt;
- struct io_kiocb *req;
- int nr_entries;
- int error;
- bool owning;
- /* output value, set only if arm poll returns >0 */
- __poll_t result_mask;
- };
- #define IO_POLL_CANCEL_FLAG BIT(31)
- #define IO_POLL_RETRY_FLAG BIT(30)
- #define IO_POLL_REF_MASK GENMASK(29, 0)
- /*
- * We usually have 1-2 refs taken, 128 is more than enough and we want to
- * maximise the margin between this amount and the moment when it overflows.
- */
- #define IO_POLL_REF_BIAS 128
- #define IO_WQE_F_DOUBLE 1
- static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
- void *key);
- static inline struct io_kiocb *wqe_to_req(struct wait_queue_entry *wqe)
- {
- unsigned long priv = (unsigned long)wqe->private;
- return (struct io_kiocb *)(priv & ~IO_WQE_F_DOUBLE);
- }
- static inline bool wqe_is_double(struct wait_queue_entry *wqe)
- {
- unsigned long priv = (unsigned long)wqe->private;
- return priv & IO_WQE_F_DOUBLE;
- }
- static bool io_poll_get_ownership_slowpath(struct io_kiocb *req)
- {
- int v;
- /*
- * poll_refs are already elevated and we don't have much hope for
- * grabbing the ownership. Instead of incrementing set a retry flag
- * to notify the loop that there might have been some change.
- */
- v = atomic_fetch_or(IO_POLL_RETRY_FLAG, &req->poll_refs);
- if (v & IO_POLL_REF_MASK)
- return false;
- return !(atomic_fetch_inc(&req->poll_refs) & IO_POLL_REF_MASK);
- }
- /*
- * If refs part of ->poll_refs (see IO_POLL_REF_MASK) is 0, it's free. We can
- * bump it and acquire ownership. It's disallowed to modify requests while not
- * owning it, that prevents from races for enqueueing task_work's and b/w
- * arming poll and wakeups.
- */
- static inline bool io_poll_get_ownership(struct io_kiocb *req)
- {
- if (unlikely(atomic_read(&req->poll_refs) >= IO_POLL_REF_BIAS))
- return io_poll_get_ownership_slowpath(req);
- return !(atomic_fetch_inc(&req->poll_refs) & IO_POLL_REF_MASK);
- }
- static void io_poll_mark_cancelled(struct io_kiocb *req)
- {
- atomic_or(IO_POLL_CANCEL_FLAG, &req->poll_refs);
- }
- static struct io_poll *io_poll_get_double(struct io_kiocb *req)
- {
- /* pure poll stashes this in ->async_data, poll driven retry elsewhere */
- if (req->opcode == IORING_OP_POLL_ADD)
- return req->async_data;
- return req->apoll->double_poll;
- }
- static struct io_poll *io_poll_get_single(struct io_kiocb *req)
- {
- if (req->opcode == IORING_OP_POLL_ADD)
- return io_kiocb_to_cmd(req, struct io_poll);
- return &req->apoll->poll;
- }
- static void io_poll_req_insert(struct io_kiocb *req)
- {
- struct io_hash_table *table = &req->ctx->cancel_table;
- u32 index = hash_long(req->cqe.user_data, table->hash_bits);
- lockdep_assert_held(&req->ctx->uring_lock);
- hlist_add_head(&req->hash_node, &table->hbs[index].list);
- }
- static void io_init_poll_iocb(struct io_poll *poll, __poll_t events)
- {
- poll->head = NULL;
- #define IO_POLL_UNMASK (EPOLLERR|EPOLLHUP|EPOLLNVAL|EPOLLRDHUP)
- /* mask in events that we always want/need */
- poll->events = events | IO_POLL_UNMASK;
- INIT_LIST_HEAD(&poll->wait.entry);
- init_waitqueue_func_entry(&poll->wait, io_poll_wake);
- }
- static void io_poll_remove_waitq(struct io_poll *poll)
- {
- /*
- * If the waitqueue is being freed early but someone is already holds
- * ownership over it, we have to tear down the request as best we can.
- * That means immediately removing the request from its waitqueue and
- * preventing all further accesses to the waitqueue via the request.
- */
- list_del_init(&poll->wait.entry);
- /*
- * Careful: this *must* be the last step, since as soon as req->head is
- * NULL'ed out, the request can be completed and freed, since
- * io_poll_remove_entry() will no longer need to take the waitqueue
- * lock.
- */
- smp_store_release(&poll->head, NULL);
- }
- static inline void io_poll_remove_entry(struct io_poll *poll)
- {
- struct wait_queue_head *head = smp_load_acquire(&poll->head);
- if (head) {
- spin_lock_irq(&head->lock);
- io_poll_remove_waitq(poll);
- spin_unlock_irq(&head->lock);
- }
- }
- static void io_poll_remove_entries(struct io_kiocb *req)
- {
- /*
- * Nothing to do if neither of those flags are set. Avoid dipping
- * into the poll/apoll/double cachelines if we can.
- */
- if (!(req->flags & (REQ_F_SINGLE_POLL | REQ_F_DOUBLE_POLL)))
- return;
- /*
- * While we hold the waitqueue lock and the waitqueue is nonempty,
- * wake_up_pollfree() will wait for us. However, taking the waitqueue
- * lock in the first place can race with the waitqueue being freed.
- *
- * We solve this as eventpoll does: by taking advantage of the fact that
- * all users of wake_up_pollfree() will RCU-delay the actual free. If
- * we enter rcu_read_lock() and see that the pointer to the queue is
- * non-NULL, we can then lock it without the memory being freed out from
- * under us.
- *
- * Keep holding rcu_read_lock() as long as we hold the queue lock, in
- * case the caller deletes the entry from the queue, leaving it empty.
- * In that case, only RCU prevents the queue memory from being freed.
- */
- rcu_read_lock();
- if (req->flags & REQ_F_SINGLE_POLL)
- io_poll_remove_entry(io_poll_get_single(req));
- if (req->flags & REQ_F_DOUBLE_POLL)
- io_poll_remove_entry(io_poll_get_double(req));
- rcu_read_unlock();
- }
- enum {
- IOU_POLL_DONE = 0,
- IOU_POLL_NO_ACTION = 1,
- IOU_POLL_REMOVE_POLL_USE_RES = 2,
- IOU_POLL_REISSUE = 3,
- IOU_POLL_REQUEUE = 4,
- };
- static void __io_poll_execute(struct io_kiocb *req, int mask)
- {
- unsigned flags = 0;
- io_req_set_res(req, mask, 0);
- req->io_task_work.func = io_poll_task_func;
- trace_io_uring_task_add(req, mask);
- if (!(req->flags & REQ_F_POLL_NO_LAZY))
- flags = IOU_F_TWQ_LAZY_WAKE;
- __io_req_task_work_add(req, flags);
- }
- static inline void io_poll_execute(struct io_kiocb *req, int res)
- {
- if (io_poll_get_ownership(req))
- __io_poll_execute(req, res);
- }
- /*
- * All poll tw should go through this. Checks for poll events, manages
- * references, does rewait, etc.
- *
- * Returns a negative error on failure. IOU_POLL_NO_ACTION when no action
- * require, which is either spurious wakeup or multishot CQE is served.
- * IOU_POLL_DONE when it's done with the request, then the mask is stored in
- * req->cqe.res. IOU_POLL_REMOVE_POLL_USE_RES indicates to remove multishot
- * poll and that the result is stored in req->cqe.
- */
- static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw)
- {
- int v;
- if (unlikely(tw.cancel))
- return -ECANCELED;
- do {
- v = atomic_read(&req->poll_refs);
- if (unlikely(v != 1)) {
- /* tw should be the owner and so have some refs */
- if (WARN_ON_ONCE(!(v & IO_POLL_REF_MASK)))
- return IOU_POLL_NO_ACTION;
- if (v & IO_POLL_CANCEL_FLAG)
- return -ECANCELED;
- /*
- * cqe.res contains only events of the first wake up
- * and all others are to be lost. Redo vfs_poll() to get
- * up to date state.
- */
- if ((v & IO_POLL_REF_MASK) != 1)
- req->cqe.res = 0;
- if (v & IO_POLL_RETRY_FLAG) {
- req->cqe.res = 0;
- /*
- * We won't find new events that came in between
- * vfs_poll and the ref put unless we clear the
- * flag in advance.
- */
- atomic_andnot(IO_POLL_RETRY_FLAG, &req->poll_refs);
- v &= ~IO_POLL_RETRY_FLAG;
- }
- v &= IO_POLL_REF_MASK;
- }
- /* the mask was stashed in __io_poll_execute */
- if (!req->cqe.res) {
- struct poll_table_struct pt = { ._key = req->apoll_events };
- req->cqe.res = vfs_poll(req->file, &pt) & req->apoll_events;
- /*
- * We got woken with a mask, but someone else got to
- * it first. The above vfs_poll() doesn't add us back
- * to the waitqueue, so if we get nothing back, we
- * should be safe and attempt a reissue.
- */
- if (unlikely(!req->cqe.res)) {
- /* Multishot armed need not reissue */
- if (!(req->apoll_events & EPOLLONESHOT))
- continue;
- return IOU_POLL_REISSUE;
- }
- }
- if (req->apoll_events & EPOLLONESHOT)
- return IOU_POLL_DONE;
- /* multishot, just fill a CQE and proceed */
- if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
- __poll_t mask = mangle_poll(req->cqe.res &
- req->apoll_events);
- if (!io_req_post_cqe(req, mask, IORING_CQE_F_MORE)) {
- io_req_set_res(req, mask, 0);
- return IOU_POLL_REMOVE_POLL_USE_RES;
- }
- } else {
- int ret;
- /* multiple refs and HUP, ensure we loop once more */
- if ((req->cqe.res & (POLLHUP | POLLRDHUP)) && v != 1)
- v--;
- ret = io_poll_issue(req, tw);
- if (ret == IOU_COMPLETE)
- return IOU_POLL_REMOVE_POLL_USE_RES;
- else if (ret == IOU_REQUEUE)
- return IOU_POLL_REQUEUE;
- if (ret != IOU_RETRY && ret < 0)
- return ret;
- }
- /* force the next iteration to vfs_poll() */
- req->cqe.res = 0;
- /*
- * Release all references, retry if someone tried to restart
- * task_work while we were executing it.
- */
- } while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK);
- io_napi_add(req);
- return IOU_POLL_NO_ACTION;
- }
- void io_poll_task_func(struct io_tw_req tw_req, io_tw_token_t tw)
- {
- struct io_kiocb *req = tw_req.req;
- int ret;
- ret = io_poll_check_events(req, tw);
- if (ret == IOU_POLL_NO_ACTION) {
- return;
- } else if (ret == IOU_POLL_REQUEUE) {
- __io_poll_execute(req, 0);
- return;
- }
- io_poll_remove_entries(req);
- /* task_work always has ->uring_lock held */
- hash_del(&req->hash_node);
- if (req->opcode == IORING_OP_POLL_ADD) {
- if (ret == IOU_POLL_DONE) {
- struct io_poll *poll;
- poll = io_kiocb_to_cmd(req, struct io_poll);
- req->cqe.res = mangle_poll(req->cqe.res & poll->events);
- } else if (ret == IOU_POLL_REISSUE) {
- io_req_task_submit(tw_req, tw);
- return;
- } else if (ret != IOU_POLL_REMOVE_POLL_USE_RES) {
- req->cqe.res = ret;
- req_set_fail(req);
- }
- io_req_set_res(req, req->cqe.res, 0);
- io_req_task_complete(tw_req, tw);
- } else {
- io_tw_lock(req->ctx, tw);
- if (ret == IOU_POLL_REMOVE_POLL_USE_RES)
- io_req_task_complete(tw_req, tw);
- else if (ret == IOU_POLL_DONE || ret == IOU_POLL_REISSUE)
- io_req_task_submit(tw_req, tw);
- else
- io_req_defer_failed(req, ret);
- }
- }
- 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);
- }
- #define IO_ASYNC_POLL_COMMON (EPOLLONESHOT | EPOLLPRI)
- static __cold int io_pollfree_wake(struct io_kiocb *req, struct io_poll *poll)
- {
- io_poll_mark_cancelled(req);
- /* we have to kick tw in case it's not already */
- io_poll_execute(req, 0);
- io_poll_remove_waitq(poll);
- return 1;
- }
- static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
- void *key)
- {
- struct io_kiocb *req = wqe_to_req(wait);
- struct io_poll *poll = container_of(wait, struct io_poll, wait);
- __poll_t mask = key_to_poll(key);
- if (unlikely(mask & POLLFREE))
- return io_pollfree_wake(req, poll);
- /* for instances that support it check for an event match first */
- if (mask && !(mask & (poll->events & ~IO_ASYNC_POLL_COMMON)))
- return 0;
- if (io_poll_get_ownership(req)) {
- /*
- * If we trigger a multishot poll off our own wakeup path,
- * disable multishot as there is a circular dependency between
- * CQ posting and triggering the event.
- */
- if (mask & EPOLL_URING_WAKE)
- poll->events |= EPOLLONESHOT;
- /* optional, saves extra locking for removal in tw handler */
- if (mask && poll->events & EPOLLONESHOT) {
- io_poll_remove_waitq(poll);
- if (wqe_is_double(wait))
- req->flags &= ~REQ_F_DOUBLE_POLL;
- else
- req->flags &= ~REQ_F_SINGLE_POLL;
- }
- __io_poll_execute(req, mask);
- }
- return 1;
- }
- /* fails only when polling is already completing by the first entry */
- static bool io_poll_double_prepare(struct io_kiocb *req)
- {
- struct wait_queue_head *head;
- struct io_poll *poll = io_poll_get_single(req);
- /* head is RCU protected, see io_poll_remove_entries() comments */
- rcu_read_lock();
- head = smp_load_acquire(&poll->head);
- /*
- * poll arm might not hold ownership and so race for req->flags with
- * io_poll_wake(). There is only one poll entry queued, serialise with
- * it by taking its head lock. As we're still arming the tw hanlder
- * is not going to be run, so there are no races with it.
- */
- if (head) {
- spin_lock_irq(&head->lock);
- req->flags |= REQ_F_DOUBLE_POLL;
- if (req->opcode == IORING_OP_POLL_ADD)
- req->flags |= REQ_F_ASYNC_DATA;
- spin_unlock_irq(&head->lock);
- }
- rcu_read_unlock();
- return !!head;
- }
- static void __io_queue_proc(struct io_poll *poll, struct io_poll_table *pt,
- struct wait_queue_head *head,
- struct io_poll **poll_ptr)
- {
- struct io_kiocb *req = pt->req;
- unsigned long wqe_private = (unsigned long) req;
- /*
- * The file being polled uses multiple waitqueues for poll handling
- * (e.g. one for read, one for write). Setup a separate io_poll
- * if this happens.
- */
- if (unlikely(pt->nr_entries)) {
- struct io_poll *first = poll;
- /* double add on the same waitqueue head, ignore */
- if (first->head == head)
- return;
- /* already have a 2nd entry, fail a third attempt */
- if (*poll_ptr) {
- if ((*poll_ptr)->head == head)
- return;
- pt->error = -EINVAL;
- return;
- }
- poll = kmalloc_obj(*poll, GFP_ATOMIC);
- if (!poll) {
- pt->error = -ENOMEM;
- return;
- }
- /* mark as double wq entry */
- wqe_private |= IO_WQE_F_DOUBLE;
- io_init_poll_iocb(poll, first->events);
- if (!io_poll_double_prepare(req)) {
- /* the request is completing, just back off */
- kfree(poll);
- return;
- }
- *poll_ptr = poll;
- } else {
- /* fine to modify, there is no poll queued to race with us */
- req->flags |= REQ_F_SINGLE_POLL;
- }
- pt->nr_entries++;
- poll->head = head;
- poll->wait.private = (void *) wqe_private;
- if (poll->events & EPOLLEXCLUSIVE) {
- add_wait_queue_exclusive(head, &poll->wait);
- } else {
- add_wait_queue(head, &poll->wait);
- }
- }
- static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
- struct poll_table_struct *p)
- {
- struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
- struct io_poll *poll = io_kiocb_to_cmd(pt->req, struct io_poll);
- __io_queue_proc(poll, pt, head,
- (struct io_poll **) &pt->req->async_data);
- }
- static bool io_poll_can_finish_inline(struct io_kiocb *req,
- struct io_poll_table *pt)
- {
- return pt->owning || io_poll_get_ownership(req);
- }
- static void io_poll_add_hash(struct io_kiocb *req, unsigned int issue_flags)
- {
- struct io_ring_ctx *ctx = req->ctx;
- io_ring_submit_lock(ctx, issue_flags);
- io_poll_req_insert(req);
- io_ring_submit_unlock(ctx, issue_flags);
- }
- /*
- * Returns 0 when it's handed over for polling. The caller owns the requests if
- * it returns non-zero, but otherwise should not touch it. Negative values
- * contain an error code. When the result is >0, the polling has completed
- * inline and ipt.result_mask is set to the mask.
- */
- static int __io_arm_poll_handler(struct io_kiocb *req,
- struct io_poll *poll,
- struct io_poll_table *ipt, __poll_t mask,
- unsigned issue_flags)
- {
- INIT_HLIST_NODE(&req->hash_node);
- io_init_poll_iocb(poll, mask);
- poll->file = req->file;
- req->apoll_events = poll->events;
- ipt->pt._key = mask;
- ipt->req = req;
- ipt->error = 0;
- ipt->nr_entries = 0;
- /*
- * Polling is either completed here or via task_work, so if we're in the
- * task context we're naturally serialised with tw by merit of running
- * the same task. When it's io-wq, take the ownership to prevent tw
- * from running. However, when we're in the task context, skip taking
- * it as an optimisation.
- *
- * Note: even though the request won't be completed/freed, without
- * ownership we still can race with io_poll_wake().
- * io_poll_can_finish_inline() tries to deal with that.
- */
- ipt->owning = issue_flags & IO_URING_F_UNLOCKED;
- atomic_set(&req->poll_refs, (int)ipt->owning);
- /*
- * Exclusive waits may only wake a limited amount of entries
- * rather than all of them, this may interfere with lazy
- * wake if someone does wait(events > 1). Ensure we don't do
- * lazy wake for those, as we need to process each one as they
- * come in.
- */
- if (poll->events & EPOLLEXCLUSIVE)
- req->flags |= REQ_F_POLL_NO_LAZY;
- mask = vfs_poll(req->file, &ipt->pt) & poll->events;
- if (unlikely(ipt->error || !ipt->nr_entries)) {
- io_poll_remove_entries(req);
- if (!io_poll_can_finish_inline(req, ipt)) {
- io_poll_mark_cancelled(req);
- return 0;
- } else if (mask && (poll->events & EPOLLET)) {
- ipt->result_mask = mask;
- return 1;
- }
- return ipt->error ?: -EINVAL;
- }
- if (mask &&
- ((poll->events & (EPOLLET|EPOLLONESHOT)) == (EPOLLET|EPOLLONESHOT))) {
- if (!io_poll_can_finish_inline(req, ipt)) {
- io_poll_add_hash(req, issue_flags);
- return 0;
- }
- io_poll_remove_entries(req);
- ipt->result_mask = mask;
- /* no one else has access to the req, forget about the ref */
- return 1;
- }
- io_poll_add_hash(req, issue_flags);
- if (mask && (poll->events & EPOLLET) &&
- io_poll_can_finish_inline(req, ipt)) {
- __io_poll_execute(req, mask);
- return 0;
- }
- io_napi_add(req);
- if (ipt->owning) {
- /*
- * Try to release ownership. If we see a change of state, e.g.
- * poll was waken up, queue up a tw, it'll deal with it.
- */
- if (atomic_cmpxchg(&req->poll_refs, 1, 0) != 1)
- __io_poll_execute(req, 0);
- }
- return 0;
- }
- static void io_async_queue_proc(struct file *file, struct wait_queue_head *head,
- struct poll_table_struct *p)
- {
- struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
- struct async_poll *apoll = pt->req->apoll;
- __io_queue_proc(&apoll->poll, pt, head, &apoll->double_poll);
- }
- /*
- * We can't reliably detect loops in repeated poll triggers and issue
- * subsequently failing. But rather than fail these immediately, allow a
- * certain amount of retries before we give up. Given that this condition
- * should _rarely_ trigger even once, we should be fine with a larger value.
- */
- #define APOLL_MAX_RETRY 128
- static struct async_poll *io_req_alloc_apoll(struct io_kiocb *req,
- unsigned issue_flags)
- {
- struct io_ring_ctx *ctx = req->ctx;
- struct async_poll *apoll;
- if (req->flags & REQ_F_POLLED) {
- apoll = req->apoll;
- kfree(apoll->double_poll);
- } else {
- if (!(issue_flags & IO_URING_F_UNLOCKED))
- apoll = io_cache_alloc(&ctx->apoll_cache, GFP_ATOMIC);
- else
- apoll = kmalloc_obj(*apoll, GFP_ATOMIC);
- if (!apoll)
- return NULL;
- apoll->poll.retries = APOLL_MAX_RETRY;
- }
- apoll->double_poll = NULL;
- req->apoll = apoll;
- if (unlikely(!--apoll->poll.retries))
- return NULL;
- return apoll;
- }
- int io_arm_apoll(struct io_kiocb *req, unsigned issue_flags, __poll_t mask)
- {
- struct async_poll *apoll;
- struct io_poll_table ipt;
- int ret;
- mask |= EPOLLET;
- if (!io_file_can_poll(req))
- return IO_APOLL_ABORTED;
- if (!(req->flags & REQ_F_APOLL_MULTISHOT))
- mask |= EPOLLONESHOT;
- apoll = io_req_alloc_apoll(req, issue_flags);
- if (!apoll)
- return IO_APOLL_ABORTED;
- req->flags &= ~(REQ_F_SINGLE_POLL | REQ_F_DOUBLE_POLL);
- req->flags |= REQ_F_POLLED;
- ipt.pt._qproc = io_async_queue_proc;
- ret = __io_arm_poll_handler(req, &apoll->poll, &ipt, mask, issue_flags);
- if (ret)
- return ret > 0 ? IO_APOLL_READY : IO_APOLL_ABORTED;
- trace_io_uring_poll_arm(req, mask, apoll->poll.events);
- return IO_APOLL_OK;
- }
- int io_arm_poll_handler(struct io_kiocb *req, unsigned issue_flags)
- {
- const struct io_issue_def *def = &io_issue_defs[req->opcode];
- __poll_t mask = POLLPRI | POLLERR;
- if (!def->pollin && !def->pollout)
- return IO_APOLL_ABORTED;
- if (!io_file_can_poll(req))
- return IO_APOLL_ABORTED;
- if (def->pollin) {
- mask |= EPOLLIN | EPOLLRDNORM;
- /* If reading from MSG_ERRQUEUE using recvmsg, ignore POLLIN */
- if (req->flags & REQ_F_CLEAR_POLLIN)
- mask &= ~EPOLLIN;
- } else {
- mask |= EPOLLOUT | EPOLLWRNORM;
- }
- if (def->poll_exclusive)
- mask |= EPOLLEXCLUSIVE;
- return io_arm_apoll(req, issue_flags, mask);
- }
- /*
- * Returns true if we found and killed one or more poll requests
- */
- __cold bool io_poll_remove_all(struct io_ring_ctx *ctx, struct io_uring_task *tctx,
- bool cancel_all)
- {
- unsigned nr_buckets = 1U << ctx->cancel_table.hash_bits;
- struct hlist_node *tmp;
- struct io_kiocb *req;
- bool found = false;
- int i;
- lockdep_assert_held(&ctx->uring_lock);
- for (i = 0; i < nr_buckets; i++) {
- struct io_hash_bucket *hb = &ctx->cancel_table.hbs[i];
- hlist_for_each_entry_safe(req, tmp, &hb->list, hash_node) {
- if (io_match_task_safe(req, tctx, cancel_all)) {
- hlist_del_init(&req->hash_node);
- io_poll_cancel_req(req);
- found = true;
- }
- }
- }
- return found;
- }
- static struct io_kiocb *io_poll_find(struct io_ring_ctx *ctx, bool poll_only,
- struct io_cancel_data *cd)
- {
- struct io_kiocb *req;
- u32 index = hash_long(cd->data, ctx->cancel_table.hash_bits);
- struct io_hash_bucket *hb = &ctx->cancel_table.hbs[index];
- hlist_for_each_entry(req, &hb->list, hash_node) {
- if (cd->data != req->cqe.user_data)
- continue;
- if (poll_only && req->opcode != IORING_OP_POLL_ADD)
- continue;
- if (cd->flags & IORING_ASYNC_CANCEL_ALL) {
- if (io_cancel_match_sequence(req, cd->seq))
- continue;
- }
- return req;
- }
- return NULL;
- }
- static struct io_kiocb *io_poll_file_find(struct io_ring_ctx *ctx,
- struct io_cancel_data *cd)
- {
- unsigned nr_buckets = 1U << ctx->cancel_table.hash_bits;
- struct io_kiocb *req;
- int i;
- for (i = 0; i < nr_buckets; i++) {
- struct io_hash_bucket *hb = &ctx->cancel_table.hbs[i];
- hlist_for_each_entry(req, &hb->list, hash_node) {
- if (io_cancel_req_match(req, cd))
- return req;
- }
- }
- return NULL;
- }
- static int io_poll_disarm(struct io_kiocb *req)
- {
- if (!req)
- return -ENOENT;
- if (!io_poll_get_ownership(req))
- return -EALREADY;
- io_poll_remove_entries(req);
- hash_del(&req->hash_node);
- return 0;
- }
- static int __io_poll_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd)
- {
- struct io_kiocb *req;
- if (cd->flags & (IORING_ASYNC_CANCEL_FD | IORING_ASYNC_CANCEL_OP |
- IORING_ASYNC_CANCEL_ANY))
- req = io_poll_file_find(ctx, cd);
- else
- req = io_poll_find(ctx, false, cd);
- if (req) {
- io_poll_cancel_req(req);
- return 0;
- }
- return -ENOENT;
- }
- int io_poll_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd,
- unsigned issue_flags)
- {
- int ret;
- io_ring_submit_lock(ctx, issue_flags);
- ret = __io_poll_cancel(ctx, cd);
- io_ring_submit_unlock(ctx, issue_flags);
- return ret;
- }
- static __poll_t io_poll_parse_events(const struct io_uring_sqe *sqe,
- unsigned int flags)
- {
- u32 events;
- events = READ_ONCE(sqe->poll32_events);
- #ifdef __BIG_ENDIAN
- events = swahw32(events);
- #endif
- if (!(flags & IORING_POLL_ADD_MULTI))
- events |= EPOLLONESHOT;
- if (!(flags & IORING_POLL_ADD_LEVEL))
- events |= EPOLLET;
- return demangle_poll(events) |
- (events & (EPOLLEXCLUSIVE|EPOLLONESHOT|EPOLLET));
- }
- int io_poll_remove_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
- {
- struct io_poll_update *upd = io_kiocb_to_cmd(req, struct io_poll_update);
- u32 flags;
- if (sqe->buf_index || sqe->splice_fd_in)
- return -EINVAL;
- flags = READ_ONCE(sqe->len);
- if (flags & ~(IORING_POLL_UPDATE_EVENTS | IORING_POLL_UPDATE_USER_DATA |
- IORING_POLL_ADD_MULTI))
- return -EINVAL;
- /* meaningless without update */
- if (flags == IORING_POLL_ADD_MULTI)
- return -EINVAL;
- upd->old_user_data = READ_ONCE(sqe->addr);
- upd->update_events = flags & IORING_POLL_UPDATE_EVENTS;
- upd->update_user_data = flags & IORING_POLL_UPDATE_USER_DATA;
- upd->new_user_data = READ_ONCE(sqe->off);
- if (!upd->update_user_data && upd->new_user_data)
- return -EINVAL;
- if (upd->update_events)
- upd->events = io_poll_parse_events(sqe, flags);
- else if (sqe->poll32_events)
- return -EINVAL;
- return 0;
- }
- int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
- {
- struct io_poll *poll = io_kiocb_to_cmd(req, struct io_poll);
- u32 flags;
- if (sqe->buf_index || sqe->off || sqe->addr)
- return -EINVAL;
- flags = READ_ONCE(sqe->len);
- if (flags & ~IORING_POLL_ADD_MULTI)
- return -EINVAL;
- if ((flags & IORING_POLL_ADD_MULTI) && (req->flags & REQ_F_CQE_SKIP))
- return -EINVAL;
- poll->events = io_poll_parse_events(sqe, flags);
- return 0;
- }
- int io_poll_add(struct io_kiocb *req, unsigned int issue_flags)
- {
- struct io_poll *poll = io_kiocb_to_cmd(req, struct io_poll);
- struct io_poll_table ipt;
- int ret;
- ipt.pt._qproc = io_poll_queue_proc;
- ret = __io_arm_poll_handler(req, poll, &ipt, poll->events, issue_flags);
- if (ret > 0) {
- io_req_set_res(req, ipt.result_mask, 0);
- return IOU_COMPLETE;
- }
- return ret ?: IOU_ISSUE_SKIP_COMPLETE;
- }
- int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
- {
- struct io_poll_update *poll_update = io_kiocb_to_cmd(req, struct io_poll_update);
- struct io_ring_ctx *ctx = req->ctx;
- struct io_cancel_data cd = { .ctx = ctx, .data = poll_update->old_user_data, };
- struct io_kiocb *preq;
- int ret2, ret = 0;
- io_ring_submit_lock(ctx, issue_flags);
- preq = io_poll_find(ctx, true, &cd);
- ret2 = io_poll_disarm(preq);
- if (ret2) {
- ret = ret2;
- goto out;
- }
- if (WARN_ON_ONCE(preq->opcode != IORING_OP_POLL_ADD)) {
- ret = -EFAULT;
- goto out;
- }
- if (poll_update->update_events || poll_update->update_user_data) {
- /* only mask one event flags, keep behavior flags */
- if (poll_update->update_events) {
- struct io_poll *poll = io_kiocb_to_cmd(preq, struct io_poll);
- poll->events &= ~0xffff;
- poll->events |= poll_update->events & 0xffff;
- poll->events |= IO_POLL_UNMASK;
- }
- if (poll_update->update_user_data)
- preq->cqe.user_data = poll_update->new_user_data;
- ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED);
- /* successfully updated, don't complete poll request */
- if (ret2 == IOU_ISSUE_SKIP_COMPLETE)
- goto out;
- /* request completed as part of the update, complete it */
- else if (ret2 == IOU_COMPLETE)
- goto complete;
- }
- io_req_set_res(preq, -ECANCELED, 0);
- complete:
- if (preq->cqe.res < 0)
- req_set_fail(preq);
- preq->io_task_work.func = io_req_task_complete;
- io_req_task_work_add(preq);
- out:
- io_ring_submit_unlock(ctx, issue_flags);
- if (ret < 0) {
- req_set_fail(req);
- return ret;
- }
- /* complete update request, we're done with it */
- io_req_set_res(req, ret, 0);
- return IOU_COMPLETE;
- }
|