17aaff708SJens Axboe // SPDX-License-Identifier: GPL-2.0 27aaff708SJens Axboe #include <linux/kernel.h> 37aaff708SJens Axboe #include <linux/errno.h> 47aaff708SJens Axboe #include <linux/fs.h> 57aaff708SJens Axboe #include <linux/file.h> 67aaff708SJens Axboe #include <linux/mm.h> 77aaff708SJens Axboe #include <linux/slab.h> 87aaff708SJens Axboe #include <linux/namei.h> 97aaff708SJens Axboe #include <linux/io_uring.h> 107aaff708SJens Axboe 117aaff708SJens Axboe #include <uapi/linux/io_uring.h> 127aaff708SJens Axboe 137aaff708SJens Axboe #include "io_uring_types.h" 147aaff708SJens Axboe #include "io_uring.h" 157aaff708SJens Axboe #include "tctx.h" 167aaff708SJens Axboe #include "poll.h" 177aaff708SJens Axboe #include "timeout.h" 187aaff708SJens Axboe #include "cancel.h" 197aaff708SJens Axboe 207aaff708SJens Axboe struct io_cancel { 217aaff708SJens Axboe struct file *file; 227aaff708SJens Axboe u64 addr; 237aaff708SJens Axboe u32 flags; 247aaff708SJens Axboe s32 fd; 257aaff708SJens Axboe }; 267aaff708SJens Axboe 277aaff708SJens Axboe #define CANCEL_FLAGS (IORING_ASYNC_CANCEL_ALL | IORING_ASYNC_CANCEL_FD | \ 287aaff708SJens Axboe IORING_ASYNC_CANCEL_ANY) 297aaff708SJens Axboe 307aaff708SJens Axboe static bool io_cancel_cb(struct io_wq_work *work, void *data) 317aaff708SJens Axboe { 327aaff708SJens Axboe struct io_kiocb *req = container_of(work, struct io_kiocb, work); 337aaff708SJens Axboe struct io_cancel_data *cd = data; 347aaff708SJens Axboe 357aaff708SJens Axboe if (req->ctx != cd->ctx) 367aaff708SJens Axboe return false; 377aaff708SJens Axboe if (cd->flags & IORING_ASYNC_CANCEL_ANY) { 387aaff708SJens Axboe ; 397aaff708SJens Axboe } else if (cd->flags & IORING_ASYNC_CANCEL_FD) { 407aaff708SJens Axboe if (req->file != cd->file) 417aaff708SJens Axboe return false; 427aaff708SJens Axboe } else { 437aaff708SJens Axboe if (req->cqe.user_data != cd->data) 447aaff708SJens Axboe return false; 457aaff708SJens Axboe } 467aaff708SJens Axboe if (cd->flags & (IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_ANY)) { 477aaff708SJens Axboe if (cd->seq == req->work.cancel_seq) 487aaff708SJens Axboe return false; 497aaff708SJens Axboe req->work.cancel_seq = cd->seq; 507aaff708SJens Axboe } 517aaff708SJens Axboe return true; 527aaff708SJens Axboe } 537aaff708SJens Axboe 547aaff708SJens Axboe static int io_async_cancel_one(struct io_uring_task *tctx, 557aaff708SJens Axboe struct io_cancel_data *cd) 567aaff708SJens Axboe { 577aaff708SJens Axboe enum io_wq_cancel cancel_ret; 587aaff708SJens Axboe int ret = 0; 597aaff708SJens Axboe bool all; 607aaff708SJens Axboe 617aaff708SJens Axboe if (!tctx || !tctx->io_wq) 627aaff708SJens Axboe return -ENOENT; 637aaff708SJens Axboe 647aaff708SJens Axboe all = cd->flags & (IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_ANY); 657aaff708SJens Axboe cancel_ret = io_wq_cancel_cb(tctx->io_wq, io_cancel_cb, cd, all); 667aaff708SJens Axboe switch (cancel_ret) { 677aaff708SJens Axboe case IO_WQ_CANCEL_OK: 687aaff708SJens Axboe ret = 0; 697aaff708SJens Axboe break; 707aaff708SJens Axboe case IO_WQ_CANCEL_RUNNING: 717aaff708SJens Axboe ret = -EALREADY; 727aaff708SJens Axboe break; 737aaff708SJens Axboe case IO_WQ_CANCEL_NOTFOUND: 747aaff708SJens Axboe ret = -ENOENT; 757aaff708SJens Axboe break; 767aaff708SJens Axboe } 777aaff708SJens Axboe 787aaff708SJens Axboe return ret; 797aaff708SJens Axboe } 807aaff708SJens Axboe 81*5d7943d9SPavel Begunkov int io_try_cancel(struct io_kiocb *req, struct io_cancel_data *cd, 82*5d7943d9SPavel Begunkov unsigned issue_flags) 837aaff708SJens Axboe { 847aaff708SJens Axboe struct io_ring_ctx *ctx = req->ctx; 857aaff708SJens Axboe int ret; 867aaff708SJens Axboe 877aaff708SJens Axboe WARN_ON_ONCE(!io_wq_current_is_worker() && req->task != current); 887aaff708SJens Axboe 897aaff708SJens Axboe ret = io_async_cancel_one(req->task->io_uring, cd); 907aaff708SJens Axboe /* 917aaff708SJens Axboe * Fall-through even for -EALREADY, as we may have poll armed 927aaff708SJens Axboe * that need unarming. 937aaff708SJens Axboe */ 947aaff708SJens Axboe if (!ret) 957aaff708SJens Axboe return 0; 967aaff708SJens Axboe 97*5d7943d9SPavel Begunkov ret = io_poll_cancel(ctx, cd, issue_flags); 987aaff708SJens Axboe if (ret != -ENOENT) 994dfab8abSPavel Begunkov return ret; 1004dfab8abSPavel Begunkov 10138513c46SHao Xu spin_lock(&ctx->completion_lock); 1027aaff708SJens Axboe if (!(cd->flags & IORING_ASYNC_CANCEL_FD)) 1037aaff708SJens Axboe ret = io_timeout_cancel(ctx, cd); 1047aaff708SJens Axboe spin_unlock(&ctx->completion_lock); 1057aaff708SJens Axboe return ret; 1067aaff708SJens Axboe } 1077aaff708SJens Axboe 1087aaff708SJens Axboe 1097aaff708SJens Axboe int io_async_cancel_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 1107aaff708SJens Axboe { 1117aaff708SJens Axboe struct io_cancel *cancel = io_kiocb_to_cmd(req); 1127aaff708SJens Axboe 1137aaff708SJens Axboe if (unlikely(req->flags & REQ_F_BUFFER_SELECT)) 1147aaff708SJens Axboe return -EINVAL; 1157aaff708SJens Axboe if (sqe->off || sqe->len || sqe->splice_fd_in) 1167aaff708SJens Axboe return -EINVAL; 1177aaff708SJens Axboe 1187aaff708SJens Axboe cancel->addr = READ_ONCE(sqe->addr); 1197aaff708SJens Axboe cancel->flags = READ_ONCE(sqe->cancel_flags); 1207aaff708SJens Axboe if (cancel->flags & ~CANCEL_FLAGS) 1217aaff708SJens Axboe return -EINVAL; 1227aaff708SJens Axboe if (cancel->flags & IORING_ASYNC_CANCEL_FD) { 1237aaff708SJens Axboe if (cancel->flags & IORING_ASYNC_CANCEL_ANY) 1247aaff708SJens Axboe return -EINVAL; 1257aaff708SJens Axboe cancel->fd = READ_ONCE(sqe->fd); 1267aaff708SJens Axboe } 1277aaff708SJens Axboe 1287aaff708SJens Axboe return 0; 1297aaff708SJens Axboe } 1307aaff708SJens Axboe 1317aaff708SJens Axboe static int __io_async_cancel(struct io_cancel_data *cd, struct io_kiocb *req, 1327aaff708SJens Axboe unsigned int issue_flags) 1337aaff708SJens Axboe { 1347aaff708SJens Axboe bool all = cd->flags & (IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_ANY); 1357aaff708SJens Axboe struct io_ring_ctx *ctx = cd->ctx; 1367aaff708SJens Axboe struct io_tctx_node *node; 1377aaff708SJens Axboe int ret, nr = 0; 1387aaff708SJens Axboe 1397aaff708SJens Axboe do { 140*5d7943d9SPavel Begunkov ret = io_try_cancel(req, cd, issue_flags); 1417aaff708SJens Axboe if (ret == -ENOENT) 1427aaff708SJens Axboe break; 1437aaff708SJens Axboe if (!all) 1447aaff708SJens Axboe return ret; 1457aaff708SJens Axboe nr++; 1467aaff708SJens Axboe } while (1); 1477aaff708SJens Axboe 1487aaff708SJens Axboe /* slow path, try all io-wq's */ 1497aaff708SJens Axboe io_ring_submit_lock(ctx, issue_flags); 1507aaff708SJens Axboe ret = -ENOENT; 1517aaff708SJens Axboe list_for_each_entry(node, &ctx->tctx_list, ctx_node) { 1527aaff708SJens Axboe struct io_uring_task *tctx = node->task->io_uring; 1537aaff708SJens Axboe 1547aaff708SJens Axboe ret = io_async_cancel_one(tctx, cd); 1557aaff708SJens Axboe if (ret != -ENOENT) { 1567aaff708SJens Axboe if (!all) 1577aaff708SJens Axboe break; 1587aaff708SJens Axboe nr++; 1597aaff708SJens Axboe } 1607aaff708SJens Axboe } 1617aaff708SJens Axboe io_ring_submit_unlock(ctx, issue_flags); 1627aaff708SJens Axboe return all ? nr : ret; 1637aaff708SJens Axboe } 1647aaff708SJens Axboe 1657aaff708SJens Axboe int io_async_cancel(struct io_kiocb *req, unsigned int issue_flags) 1667aaff708SJens Axboe { 1677aaff708SJens Axboe struct io_cancel *cancel = io_kiocb_to_cmd(req); 1687aaff708SJens Axboe struct io_cancel_data cd = { 1697aaff708SJens Axboe .ctx = req->ctx, 1707aaff708SJens Axboe .data = cancel->addr, 1717aaff708SJens Axboe .flags = cancel->flags, 1727aaff708SJens Axboe .seq = atomic_inc_return(&req->ctx->cancel_seq), 1737aaff708SJens Axboe }; 1747aaff708SJens Axboe int ret; 1757aaff708SJens Axboe 1767aaff708SJens Axboe if (cd.flags & IORING_ASYNC_CANCEL_FD) { 1777aaff708SJens Axboe if (req->flags & REQ_F_FIXED_FILE) 1787aaff708SJens Axboe req->file = io_file_get_fixed(req, cancel->fd, 1797aaff708SJens Axboe issue_flags); 1807aaff708SJens Axboe else 1817aaff708SJens Axboe req->file = io_file_get_normal(req, cancel->fd); 1827aaff708SJens Axboe if (!req->file) { 1837aaff708SJens Axboe ret = -EBADF; 1847aaff708SJens Axboe goto done; 1857aaff708SJens Axboe } 1867aaff708SJens Axboe cd.file = req->file; 1877aaff708SJens Axboe } 1887aaff708SJens Axboe 1897aaff708SJens Axboe ret = __io_async_cancel(&cd, req, issue_flags); 1907aaff708SJens Axboe done: 1917aaff708SJens Axboe if (ret < 0) 1927aaff708SJens Axboe req_set_fail(req); 1937aaff708SJens Axboe io_req_set_res(req, ret, 0); 1947aaff708SJens Axboe return IOU_OK; 1957aaff708SJens Axboe } 19638513c46SHao Xu 197e6f89be6SPavel Begunkov void init_hash_table(struct io_hash_table *table, unsigned size) 19838513c46SHao Xu { 19938513c46SHao Xu unsigned int i; 20038513c46SHao Xu 20138513c46SHao Xu for (i = 0; i < size; i++) { 202e6f89be6SPavel Begunkov spin_lock_init(&table->hbs[i].lock); 203e6f89be6SPavel Begunkov INIT_HLIST_HEAD(&table->hbs[i].list); 20438513c46SHao Xu } 20538513c46SHao Xu } 206