Completion of io_uring_cmd ioctl may involve referencing certain ioctl-specefic fields, requiring original submitter-context. Introduce two APIs for that purpose: a. io_uring_cmd_complete_in_task b. io_uring_cbh_to_io_uring_cmd The APIs facilitate reusing task-work infra, while driver gets to implement ioctl-specific handling in a callback. Signed-off-by: Kanchan Joshi <joshi.k@xxxxxxxxxxx> Signed-off-by: Anuj Gupta <anuj20.g@xxxxxxxxxxx> --- fs/io_uring.c | 23 +++++++++++++++++++++++ include/linux/io_uring.h | 12 ++++++++++++ 2 files changed, 35 insertions(+) diff --git a/fs/io_uring.c b/fs/io_uring.c index b6e1b6b51c5f..a8629c460bdd 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2079,6 +2079,29 @@ static void io_req_task_submit(struct callback_head *cb) __io_req_task_submit(req); } +struct io_uring_cmd *io_uring_cbh_to_io_uring_cmd(struct callback_head *cb) +{ + return &container_of(cb, struct io_kiocb, task_work)->uring_cmd; +} +EXPORT_SYMBOL_GPL(io_uring_cbh_to_io_uring_cmd); + +int io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd, + void (*driver_cb)(struct callback_head *)) +{ + int ret; + struct io_kiocb *req = container_of(ioucmd, struct io_kiocb, uring_cmd); + + req->task_work.func = driver_cb; + ret = io_req_task_work_add(req); + if (unlikely(ret)) { + req->result = -ECANCELED; + percpu_ref_get(&req->ctx->refs); + io_req_task_work_add_fallback(req, io_req_task_cancel); + } + return ret; +} +EXPORT_SYMBOL_GPL(io_uring_cmd_complete_in_task); + static void io_req_task_queue_fail(struct io_kiocb *req, int ret) { req->result = ret; diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h index 9956c0f5f9d0..526bc58dea25 100644 --- a/include/linux/io_uring.h +++ b/include/linux/io_uring.h @@ -19,6 +19,9 @@ struct io_uring_cmd { #if defined(CONFIG_IO_URING) void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret); +int io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd, + void (*driver_cb)(struct callback_head *)); +struct io_uring_cmd *io_uring_cbh_to_io_uring_cmd(struct callback_head *cbh); struct sock *io_uring_get_socket(struct file *file); void __io_uring_task_cancel(void); void __io_uring_files_cancel(struct files_struct *files); @@ -43,6 +46,15 @@ static inline void io_uring_free(struct task_struct *tsk) static inline void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret) { } +int io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd, + void (*driver_cb)(struct callback_head *)) +{ + return -1; +} +struct io_uring_cmd *io_uring_cbh_to_io_uring_cmd(struct callback_head *) +{ + return NULL; +} static inline struct sock *io_uring_get_socket(struct file *file) { return NULL; -- 2.25.1