1

io_uring: Pass whole sqe to commands

Currently uring CMD operation relies on having large SQEs, but future
operations might want to use normal SQE.

The io_uring_cmd currently only saves the payload (cmd) part of the SQE,
but, for commands that use normal SQE size, it might be necessary to
access the initial SQE fields outside of the payload/cmd block.  So,
saves the whole SQE other than just the pdu.

This changes slightly how the io_uring_cmd works, since the cmd
structures and callbacks are not opaque to io_uring anymore. I.e, the
callbacks can look at the SQE entries, not only, in the cmd structure.

The main advantage is that we don't need to create custom structures for
simple commands.

Creates io_uring_sqe_cmd() that returns the cmd private data as a null
pointer and avoids casting in the callee side.
Also, make most of ublk_drv's sqe->cmd priv structure into const, and use
io_uring_sqe_cmd() to get the private structure, removing the unwanted
cast. (There is one case where the cast is still needed since the
header->{len,addr} is updated in the private structure)

Suggested-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/20230504121856.904491-3-leitao@debian.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Breno Leitao 2023-05-04 05:18:55 -07:00 committed by Jens Axboe
parent 96c7d4f81d
commit fd9b8547bc
5 changed files with 24 additions and 22 deletions

View File

@ -1019,7 +1019,7 @@ static int ublk_ch_mmap(struct file *filp, struct vm_area_struct *vma)
} }
static void ublk_commit_completion(struct ublk_device *ub, static void ublk_commit_completion(struct ublk_device *ub,
struct ublksrv_io_cmd *ub_cmd) const struct ublksrv_io_cmd *ub_cmd)
{ {
u32 qid = ub_cmd->q_id, tag = ub_cmd->tag; u32 qid = ub_cmd->q_id, tag = ub_cmd->tag;
struct ublk_queue *ubq = ublk_get_queue(ub, qid); struct ublk_queue *ubq = ublk_get_queue(ub, qid);
@ -1263,7 +1263,7 @@ static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id,
static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
{ {
struct ublksrv_io_cmd *ub_cmd = (struct ublksrv_io_cmd *)cmd->cmd; const struct ublksrv_io_cmd *ub_cmd = io_uring_sqe_cmd(cmd->sqe);
struct ublk_device *ub = cmd->file->private_data; struct ublk_device *ub = cmd->file->private_data;
struct ublk_queue *ubq; struct ublk_queue *ubq;
struct ublk_io *io; struct ublk_io *io;
@ -1567,7 +1567,7 @@ static struct ublk_device *ublk_get_device_from_id(int idx)
static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd) static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
int ublksrv_pid = (int)header->data[0]; int ublksrv_pid = (int)header->data[0];
struct gendisk *disk; struct gendisk *disk;
int ret = -EINVAL; int ret = -EINVAL;
@ -1630,7 +1630,7 @@ out_unlock:
static int ublk_ctrl_get_queue_affinity(struct ublk_device *ub, static int ublk_ctrl_get_queue_affinity(struct ublk_device *ub,
struct io_uring_cmd *cmd) struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
void __user *argp = (void __user *)(unsigned long)header->addr; void __user *argp = (void __user *)(unsigned long)header->addr;
cpumask_var_t cpumask; cpumask_var_t cpumask;
unsigned long queue; unsigned long queue;
@ -1681,7 +1681,7 @@ static inline void ublk_dump_dev_info(struct ublksrv_ctrl_dev_info *info)
static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
void __user *argp = (void __user *)(unsigned long)header->addr; void __user *argp = (void __user *)(unsigned long)header->addr;
struct ublksrv_ctrl_dev_info info; struct ublksrv_ctrl_dev_info info;
struct ublk_device *ub; struct ublk_device *ub;
@ -1844,7 +1844,7 @@ static int ublk_ctrl_del_dev(struct ublk_device **p_ub)
static inline void ublk_ctrl_cmd_dump(struct io_uring_cmd *cmd) static inline void ublk_ctrl_cmd_dump(struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
pr_devel("%s: cmd_op %x, dev id %d qid %d data %llx buf %llx len %u\n", pr_devel("%s: cmd_op %x, dev id %d qid %d data %llx buf %llx len %u\n",
__func__, cmd->cmd_op, header->dev_id, header->queue_id, __func__, cmd->cmd_op, header->dev_id, header->queue_id,
@ -1863,7 +1863,7 @@ static int ublk_ctrl_stop_dev(struct ublk_device *ub)
static int ublk_ctrl_get_dev_info(struct ublk_device *ub, static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
struct io_uring_cmd *cmd) struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
void __user *argp = (void __user *)(unsigned long)header->addr; void __user *argp = (void __user *)(unsigned long)header->addr;
if (header->len < sizeof(struct ublksrv_ctrl_dev_info) || !header->addr) if (header->len < sizeof(struct ublksrv_ctrl_dev_info) || !header->addr)
@ -1894,7 +1894,7 @@ static void ublk_ctrl_fill_params_devt(struct ublk_device *ub)
static int ublk_ctrl_get_params(struct ublk_device *ub, static int ublk_ctrl_get_params(struct ublk_device *ub,
struct io_uring_cmd *cmd) struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
void __user *argp = (void __user *)(unsigned long)header->addr; void __user *argp = (void __user *)(unsigned long)header->addr;
struct ublk_params_header ph; struct ublk_params_header ph;
int ret; int ret;
@ -1925,7 +1925,7 @@ static int ublk_ctrl_get_params(struct ublk_device *ub,
static int ublk_ctrl_set_params(struct ublk_device *ub, static int ublk_ctrl_set_params(struct ublk_device *ub,
struct io_uring_cmd *cmd) struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
void __user *argp = (void __user *)(unsigned long)header->addr; void __user *argp = (void __user *)(unsigned long)header->addr;
struct ublk_params_header ph; struct ublk_params_header ph;
int ret = -EFAULT; int ret = -EFAULT;
@ -1983,7 +1983,7 @@ static void ublk_queue_reinit(struct ublk_device *ub, struct ublk_queue *ubq)
static int ublk_ctrl_start_recovery(struct ublk_device *ub, static int ublk_ctrl_start_recovery(struct ublk_device *ub,
struct io_uring_cmd *cmd) struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
int ret = -EINVAL; int ret = -EINVAL;
int i; int i;
@ -2025,7 +2025,7 @@ static int ublk_ctrl_start_recovery(struct ublk_device *ub,
static int ublk_ctrl_end_recovery(struct ublk_device *ub, static int ublk_ctrl_end_recovery(struct ublk_device *ub,
struct io_uring_cmd *cmd) struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
int ublksrv_pid = (int)header->data[0]; int ublksrv_pid = (int)header->data[0];
int ret = -EINVAL; int ret = -EINVAL;
@ -2092,7 +2092,7 @@ exit:
static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub, static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
struct io_uring_cmd *cmd) struct io_uring_cmd *cmd)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)io_uring_sqe_cmd(cmd->sqe);
bool unprivileged = ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV; bool unprivileged = ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV;
void __user *argp = (void __user *)(unsigned long)header->addr; void __user *argp = (void __user *)(unsigned long)header->addr;
char *dev_path = NULL; char *dev_path = NULL;
@ -2171,7 +2171,7 @@ exit:
static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
unsigned int issue_flags) unsigned int issue_flags)
{ {
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
struct ublk_device *ub = NULL; struct ublk_device *ub = NULL;
int ret = -EINVAL; int ret = -EINVAL;

View File

@ -552,7 +552,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
struct io_uring_cmd *ioucmd, unsigned int issue_flags, bool vec) struct io_uring_cmd *ioucmd, unsigned int issue_flags, bool vec)
{ {
struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd); struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
const struct nvme_uring_cmd *cmd = ioucmd->cmd; const struct nvme_uring_cmd *cmd = io_uring_sqe_cmd(ioucmd->sqe);
struct request_queue *q = ns ? ns->queue : ctrl->admin_q; struct request_queue *q = ns ? ns->queue : ctrl->admin_q;
struct nvme_uring_data d; struct nvme_uring_data d;
struct nvme_command c; struct nvme_command c;

View File

@ -24,7 +24,7 @@ enum io_uring_cmd_flags {
struct io_uring_cmd { struct io_uring_cmd {
struct file *file; struct file *file;
const void *cmd; const struct io_uring_sqe *sqe;
union { union {
/* callback to defer completions to task context */ /* callback to defer completions to task context */
void (*task_work_cb)(struct io_uring_cmd *cmd, unsigned); void (*task_work_cb)(struct io_uring_cmd *cmd, unsigned);
@ -66,6 +66,11 @@ static inline void io_uring_free(struct task_struct *tsk)
if (tsk->io_uring) if (tsk->io_uring)
__io_uring_free(tsk); __io_uring_free(tsk);
} }
static inline const void *io_uring_sqe_cmd(const struct io_uring_sqe *sqe)
{
return sqe->cmd;
}
#else #else
static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw, static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
struct iov_iter *iter, void *ioucmd) struct iov_iter *iter, void *ioucmd)

View File

@ -627,7 +627,7 @@ const struct io_cold_def io_cold_defs[] = {
}, },
[IORING_OP_URING_CMD] = { [IORING_OP_URING_CMD] = {
.name = "URING_CMD", .name = "URING_CMD",
.async_size = uring_cmd_pdu_size(1), .async_size = 2 * sizeof(struct io_uring_sqe),
.prep_async = io_uring_cmd_prep_async, .prep_async = io_uring_cmd_prep_async,
}, },
[IORING_OP_SEND_ZC] = { [IORING_OP_SEND_ZC] = {

View File

@ -69,15 +69,12 @@ EXPORT_SYMBOL_GPL(io_uring_cmd_done);
int io_uring_cmd_prep_async(struct io_kiocb *req) int io_uring_cmd_prep_async(struct io_kiocb *req)
{ {
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd); struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
size_t cmd_size;
BUILD_BUG_ON(uring_cmd_pdu_size(0) != 16); BUILD_BUG_ON(uring_cmd_pdu_size(0) != 16);
BUILD_BUG_ON(uring_cmd_pdu_size(1) != 80); BUILD_BUG_ON(uring_cmd_pdu_size(1) != 80);
cmd_size = uring_cmd_pdu_size(req->ctx->flags & IORING_SETUP_SQE128); memcpy(req->async_data, ioucmd->sqe, uring_sqe_size(req->ctx));
ioucmd->sqe = req->async_data;
memcpy(req->async_data, ioucmd->cmd, cmd_size);
ioucmd->cmd = req->async_data;
return 0; return 0;
} }
@ -103,7 +100,7 @@ int io_uring_cmd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
req->imu = ctx->user_bufs[index]; req->imu = ctx->user_bufs[index];
io_req_set_rsrc_node(req, ctx, 0); io_req_set_rsrc_node(req, ctx, 0);
} }
ioucmd->cmd = sqe->cmd; ioucmd->sqe = sqe;
ioucmd->cmd_op = READ_ONCE(sqe->cmd_op); ioucmd->cmd_op = READ_ONCE(sqe->cmd_op);
return 0; return 0;
} }