Skip to content

Commit 970f256

Browse files
committed
io_uring: add support for IORING_ASYNC_CANCEL_ANY
Rather than match on a specific key, be it user_data or file, allow canceling any request that we can lookup. Works like IORING_ASYNC_CANCEL_ALL in that it cancels multiple requests, but it doesn't key off user_data or the file. Can't be set with IORING_ASYNC_CANCEL_FD, as that's a key selector. Only one may be used at the time. Signed-off-by: Jens Axboe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 4bf9461 commit 970f256

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

fs/io_uring.c

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6348,7 +6348,8 @@ static struct io_kiocb *io_poll_file_find(struct io_ring_ctx *ctx,
63486348

63496349
list = &ctx->cancel_hash[i];
63506350
hlist_for_each_entry(req, list, hash_node) {
6351-
if (req->file != cd->file)
6351+
if (!(cd->flags & IORING_ASYNC_CANCEL_ANY) &&
6352+
req->file != cd->file)
63526353
continue;
63536354
if (cd->seq == req->work.cancel_seq)
63546355
continue;
@@ -6374,7 +6375,7 @@ static int io_poll_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd)
63746375
{
63756376
struct io_kiocb *req;
63766377

6377-
if (cd->flags & IORING_ASYNC_CANCEL_FD)
6378+
if (cd->flags & (IORING_ASYNC_CANCEL_FD|IORING_ASYNC_CANCEL_ANY))
63786379
req = io_poll_file_find(ctx, cd);
63796380
else
63806381
req = io_poll_find(ctx, false, cd);
@@ -6543,9 +6544,10 @@ static struct io_kiocb *io_timeout_extract(struct io_ring_ctx *ctx,
65436544
bool found = false;
65446545

65456546
list_for_each_entry(req, &ctx->timeout_list, timeout.list) {
6546-
if (cd->data != req->cqe.user_data)
6547+
if (!(cd->flags & IORING_ASYNC_CANCEL_ANY) &&
6548+
cd->data != req->cqe.user_data)
65476549
continue;
6548-
if (cd->flags & IORING_ASYNC_CANCEL_ALL) {
6550+
if (cd->flags & (IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_ANY)) {
65496551
if (cd->seq == req->work.cancel_seq)
65506552
continue;
65516553
req->work.cancel_seq = cd->seq;
@@ -6827,14 +6829,16 @@ static bool io_cancel_cb(struct io_wq_work *work, void *data)
68276829

68286830
if (req->ctx != cd->ctx)
68296831
return false;
6830-
if (cd->flags & IORING_ASYNC_CANCEL_FD) {
6832+
if (cd->flags & IORING_ASYNC_CANCEL_ANY) {
6833+
;
6834+
} else if (cd->flags & IORING_ASYNC_CANCEL_FD) {
68316835
if (req->file != cd->file)
68326836
return false;
68336837
} else {
68346838
if (req->cqe.user_data != cd->data)
68356839
return false;
68366840
}
6837-
if (cd->flags & IORING_ASYNC_CANCEL_ALL) {
6841+
if (cd->flags & (IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_ANY)) {
68386842
if (cd->seq == req->work.cancel_seq)
68396843
return false;
68406844
req->work.cancel_seq = cd->seq;
@@ -6847,12 +6851,13 @@ static int io_async_cancel_one(struct io_uring_task *tctx,
68476851
{
68486852
enum io_wq_cancel cancel_ret;
68496853
int ret = 0;
6854+
bool all;
68506855

68516856
if (!tctx || !tctx->io_wq)
68526857
return -ENOENT;
68536858

6854-
cancel_ret = io_wq_cancel_cb(tctx->io_wq, io_cancel_cb, cd,
6855-
cd->flags & IORING_ASYNC_CANCEL_ALL);
6859+
all = cd->flags & (IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_ANY);
6860+
cancel_ret = io_wq_cancel_cb(tctx->io_wq, io_cancel_cb, cd, all);
68566861
switch (cancel_ret) {
68576862
case IO_WQ_CANCEL_OK:
68586863
ret = 0;
@@ -6894,6 +6899,9 @@ static int io_try_cancel(struct io_kiocb *req, struct io_cancel_data *cd)
68946899
return ret;
68956900
}
68966901

6902+
#define CANCEL_FLAGS (IORING_ASYNC_CANCEL_ALL | IORING_ASYNC_CANCEL_FD | \
6903+
IORING_ASYNC_CANCEL_ANY)
6904+
68976905
static int io_async_cancel_prep(struct io_kiocb *req,
68986906
const struct io_uring_sqe *sqe)
68996907
{
@@ -6906,18 +6914,21 @@ static int io_async_cancel_prep(struct io_kiocb *req,
69066914

69076915
req->cancel.addr = READ_ONCE(sqe->addr);
69086916
req->cancel.flags = READ_ONCE(sqe->cancel_flags);
6909-
if (req->cancel.flags & ~(IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_FD))
6917+
if (req->cancel.flags & ~CANCEL_FLAGS)
69106918
return -EINVAL;
6911-
if (req->cancel.flags & IORING_ASYNC_CANCEL_FD)
6919+
if (req->cancel.flags & IORING_ASYNC_CANCEL_FD) {
6920+
if (req->cancel.flags & IORING_ASYNC_CANCEL_ANY)
6921+
return -EINVAL;
69126922
req->cancel.fd = READ_ONCE(sqe->fd);
6923+
}
69136924

69146925
return 0;
69156926
}
69166927

69176928
static int __io_async_cancel(struct io_cancel_data *cd, struct io_kiocb *req,
69186929
unsigned int issue_flags)
69196930
{
6920-
bool cancel_all = cd->flags & IORING_ASYNC_CANCEL_ALL;
6931+
bool all = cd->flags & (IORING_ASYNC_CANCEL_ALL|IORING_ASYNC_CANCEL_ANY);
69216932
struct io_ring_ctx *ctx = cd->ctx;
69226933
struct io_tctx_node *node;
69236934
int ret, nr = 0;
@@ -6926,7 +6937,7 @@ static int __io_async_cancel(struct io_cancel_data *cd, struct io_kiocb *req,
69266937
ret = io_try_cancel(req, cd);
69276938
if (ret == -ENOENT)
69286939
break;
6929-
if (!cancel_all)
6940+
if (!all)
69306941
return ret;
69316942
nr++;
69326943
} while (1);
@@ -6939,13 +6950,13 @@ static int __io_async_cancel(struct io_cancel_data *cd, struct io_kiocb *req,
69396950

69406951
ret = io_async_cancel_one(tctx, cd);
69416952
if (ret != -ENOENT) {
6942-
if (!cancel_all)
6953+
if (!all)
69436954
break;
69446955
nr++;
69456956
}
69466957
}
69476958
io_ring_submit_unlock(ctx, issue_flags);
6948-
return cancel_all ? nr : ret;
6959+
return all ? nr : ret;
69496960
}
69506961

69516962
static int io_async_cancel(struct io_kiocb *req, unsigned int issue_flags)

include/uapi/linux/io_uring.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,11 @@ enum {
193193
* IORING_ASYNC_CANCEL_ALL Cancel all requests that match the given key
194194
* IORING_ASYNC_CANCEL_FD Key off 'fd' for cancelation rather than the
195195
* request 'user_data'
196+
* IORING_ASYNC_CANCEL_ANY Match any request
196197
*/
197198
#define IORING_ASYNC_CANCEL_ALL (1U << 0)
198199
#define IORING_ASYNC_CANCEL_FD (1U << 1)
200+
#define IORING_ASYNC_CANCEL_ANY (1U << 2)
199201

200202
/*
201203
* IO completion data structure (Completion Queue Entry)

0 commit comments

Comments
 (0)