io_uring/cancel: add generic cancel helper
authorJens Axboe <axboe@kernel.dk>
Wed, 5 Feb 2025 20:13:58 +0000 (13:13 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 17 Feb 2025 12:34:45 +0000 (05:34 -0700)
Any opcode that is cancelable ends up defining its own cancel helper
for finding and canceling a specific request. Add a generic helper that
can be used for this purpose.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/cancel.c
io_uring/cancel.h

index 4feacc57be63bbb9cad151edb4a5208aa2581bab..0870060bac7ca42863b6bfde08b774546a3ed20c 100644 (file)
@@ -362,3 +362,24 @@ bool io_cancel_remove_all(struct io_ring_ctx *ctx, struct io_uring_task *tctx,
 
        return found;
 }
+
+int io_cancel_remove(struct io_ring_ctx *ctx, struct io_cancel_data *cd,
+                    unsigned int issue_flags, struct hlist_head *list,
+                    bool (*cancel)(struct io_kiocb *))
+{
+       struct hlist_node *tmp;
+       struct io_kiocb *req;
+       int nr = 0;
+
+       io_ring_submit_lock(ctx, issue_flags);
+       hlist_for_each_entry_safe(req, tmp, list, hash_node) {
+               if (!io_cancel_req_match(req, cd))
+                       continue;
+               if (cancel(req))
+                       nr++;
+               if (!(cd->flags & IORING_ASYNC_CANCEL_ALL))
+                       break;
+       }
+       io_ring_submit_unlock(ctx, issue_flags);
+       return nr ?: -ENOENT;
+}
index 80734a0a2b2681e0951a08a799d101af2aba0080..43e9bb74e9d19aae64ea1d9270121bf3c5c97637 100644 (file)
@@ -28,6 +28,10 @@ bool io_cancel_remove_all(struct io_ring_ctx *ctx, struct io_uring_task *tctx,
                          struct hlist_head *list, bool cancel_all,
                          bool (*cancel)(struct io_kiocb *));
 
+int io_cancel_remove(struct io_ring_ctx *ctx, struct io_cancel_data *cd,
+                    unsigned int issue_flags, struct hlist_head *list,
+                    bool (*cancel)(struct io_kiocb *));
+
 static inline bool io_cancel_match_sequence(struct io_kiocb *req, int sequence)
 {
        if (req->cancel_seq_set && sequence == req->work.cancel_seq)