Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

io_uring: cancelable uring_cmd

uring_cmd may never complete, such as ublk, in which uring cmd isn't
completed until one new block request is coming from ublk block device.

Add cancelable uring_cmd to provide mechanism to driver for cancelling
pending commands in its own way.

Add API of io_uring_cmd_mark_cancelable() for driver to mark one command as
cancelable, then io_uring will cancel this command in
io_uring_cancel_generic(). ->uring_cmd() callback is reused for canceling
command in driver's way, then driver gets notified with the cancelling
from io_uring.

Add API of io_uring_cmd_get_task() to help driver cancel handler
deal with the canceling.

Reviewed-by: Gabriel Krisman Bertazi <krisman@suse.de>
Suggested-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Ming Lei and committed by
Jens Axboe
93b8cc60 528ce678

+101
+15
include/linux/io_uring.h
··· 20 20 IO_URING_F_SQE128 = (1 << 8), 21 21 IO_URING_F_CQE32 = (1 << 9), 22 22 IO_URING_F_IOPOLL = (1 << 10), 23 + 24 + /* set when uring wants to cancel a previously issued command */ 25 + IO_URING_F_CANCEL = (1 << 11), 23 26 }; 24 27 25 28 /* only top 8 bits of sqe->uring_cmd_flags for kernel internal use */ 29 + #define IORING_URING_CMD_CANCELABLE (1U << 30) 26 30 #define IORING_URING_CMD_POLLED (1U << 31) 27 31 28 32 struct io_uring_cmd { ··· 89 85 __io_uring_free(tsk); 90 86 } 91 87 int io_uring_cmd_sock(struct io_uring_cmd *cmd, unsigned int issue_flags); 88 + void io_uring_cmd_mark_cancelable(struct io_uring_cmd *cmd, 89 + unsigned int issue_flags); 90 + struct task_struct *io_uring_cmd_get_task(struct io_uring_cmd *cmd); 92 91 #else 93 92 static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw, 94 93 struct iov_iter *iter, void *ioucmd) ··· 131 124 unsigned int issue_flags) 132 125 { 133 126 return -EOPNOTSUPP; 127 + } 128 + static inline void io_uring_cmd_mark_cancelable(struct io_uring_cmd *cmd, 129 + unsigned int issue_flags) 130 + { 131 + } 132 + static inline struct task_struct *io_uring_cmd_get_task(struct io_uring_cmd *cmd) 133 + { 134 + return NULL; 134 135 } 135 136 #endif 136 137
+6
include/linux/io_uring_types.h
··· 265 265 */ 266 266 struct io_wq_work_list iopoll_list; 267 267 bool poll_multi_queue; 268 + 269 + /* 270 + * Any cancelable uring_cmd is added to this list in 271 + * ->uring_cmd() by io_uring_cmd_insert_cancelable() 272 + */ 273 + struct hlist_head cancelable_uring_cmd; 268 274 } ____cacheline_aligned_in_smp; 269 275 270 276 struct {
+33
io_uring/io_uring.c
··· 352 352 INIT_HLIST_HEAD(&ctx->waitid_list); 353 353 INIT_DELAYED_WORK(&ctx->fallback_work, io_fallback_req_func); 354 354 INIT_WQ_LIST(&ctx->submit_state.compl_reqs); 355 + INIT_HLIST_HEAD(&ctx->cancelable_uring_cmd); 355 356 return ctx; 356 357 err: 357 358 kfree(ctx->cancel_table.hbs); ··· 3259 3258 return ret; 3260 3259 } 3261 3260 3261 + static bool io_uring_try_cancel_uring_cmd(struct io_ring_ctx *ctx, 3262 + struct task_struct *task, bool cancel_all) 3263 + { 3264 + struct hlist_node *tmp; 3265 + struct io_kiocb *req; 3266 + bool ret = false; 3267 + 3268 + lockdep_assert_held(&ctx->uring_lock); 3269 + 3270 + hlist_for_each_entry_safe(req, tmp, &ctx->cancelable_uring_cmd, 3271 + hash_node) { 3272 + struct io_uring_cmd *cmd = io_kiocb_to_cmd(req, 3273 + struct io_uring_cmd); 3274 + struct file *file = req->file; 3275 + 3276 + if (!cancel_all && req->task != task) 3277 + continue; 3278 + 3279 + if (cmd->flags & IORING_URING_CMD_CANCELABLE) { 3280 + /* ->sqe isn't available if no async data */ 3281 + if (!req_has_async_data(req)) 3282 + cmd->sqe = NULL; 3283 + file->f_op->uring_cmd(cmd, IO_URING_F_CANCEL); 3284 + ret = true; 3285 + } 3286 + } 3287 + io_submit_flush_completions(ctx); 3288 + 3289 + return ret; 3290 + } 3291 + 3262 3292 static __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx, 3263 3293 struct task_struct *task, 3264 3294 bool cancel_all) ··· 3338 3306 mutex_lock(&ctx->uring_lock); 3339 3307 ret |= io_poll_remove_all(ctx, task, cancel_all); 3340 3308 ret |= io_waitid_remove_all(ctx, task, cancel_all); 3309 + ret |= io_uring_try_cancel_uring_cmd(ctx, task, cancel_all); 3341 3310 mutex_unlock(&ctx->uring_lock); 3342 3311 ret |= io_kill_timeouts(ctx, task, cancel_all); 3343 3312 if (task)
+47
io_uring/uring_cmd.c
··· 13 13 #include "rsrc.h" 14 14 #include "uring_cmd.h" 15 15 16 + static void io_uring_cmd_del_cancelable(struct io_uring_cmd *cmd, 17 + unsigned int issue_flags) 18 + { 19 + struct io_kiocb *req = cmd_to_io_kiocb(cmd); 20 + struct io_ring_ctx *ctx = req->ctx; 21 + 22 + if (!(cmd->flags & IORING_URING_CMD_CANCELABLE)) 23 + return; 24 + 25 + cmd->flags &= ~IORING_URING_CMD_CANCELABLE; 26 + io_ring_submit_lock(ctx, issue_flags); 27 + hlist_del(&req->hash_node); 28 + io_ring_submit_unlock(ctx, issue_flags); 29 + } 30 + 31 + /* 32 + * Mark this command as concelable, then io_uring_try_cancel_uring_cmd() 33 + * will try to cancel this issued command by sending ->uring_cmd() with 34 + * issue_flags of IO_URING_F_CANCEL. 35 + * 36 + * The command is guaranteed to not be done when calling ->uring_cmd() 37 + * with IO_URING_F_CANCEL, but it is driver's responsibility to deal 38 + * with race between io_uring canceling and normal completion. 39 + */ 40 + void io_uring_cmd_mark_cancelable(struct io_uring_cmd *cmd, 41 + unsigned int issue_flags) 42 + { 43 + struct io_kiocb *req = cmd_to_io_kiocb(cmd); 44 + struct io_ring_ctx *ctx = req->ctx; 45 + 46 + if (!(cmd->flags & IORING_URING_CMD_CANCELABLE)) { 47 + cmd->flags |= IORING_URING_CMD_CANCELABLE; 48 + io_ring_submit_lock(ctx, issue_flags); 49 + hlist_add_head(&req->hash_node, &ctx->cancelable_uring_cmd); 50 + io_ring_submit_unlock(ctx, issue_flags); 51 + } 52 + } 53 + EXPORT_SYMBOL_GPL(io_uring_cmd_mark_cancelable); 54 + 55 + struct task_struct *io_uring_cmd_get_task(struct io_uring_cmd *cmd) 56 + { 57 + return cmd_to_io_kiocb(cmd)->task; 58 + } 59 + EXPORT_SYMBOL_GPL(io_uring_cmd_get_task); 60 + 16 61 static void io_uring_cmd_work(struct io_kiocb *req, struct io_tw_state *ts) 17 62 { 18 63 struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd); ··· 100 55 unsigned issue_flags) 101 56 { 102 57 struct io_kiocb *req = cmd_to_io_kiocb(ioucmd); 58 + 59 + io_uring_cmd_del_cancelable(ioucmd, issue_flags); 103 60 104 61 if (ret < 0) 105 62 req_set_fail(req);