diff options
| author | Jens Axboe <axboe@kernel.dk> | 2021-03-17 12:12:46 -0600 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2021-08-13 08:32:09 -0600 |
| commit | 834d3e42c71acf4653f840ac3998f8601f37021c (patch) | |
| tree | 402e9e526067d78bd595ceddfbb7bd5cad31c984 | |
| parent | 1aae11b1fcc03ea82ae7334d865a026c761237cc (diff) | |
| download | linux-block-834d3e42c71acf4653f840ac3998f8601f37021c.tar.gz | |
io_uring: add infrastructure around io_uring_cmd_sqe issue type
Define an io_uring_cmd_sqe struct that passthrough commands can use,
and define an array that has offset information for the two members
that we care about (user_data and personality). Then we can init the
two command types in basically the same way, just reading the user_data
and personality at the defined offsets for the command type.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
| -rw-r--r-- | fs/io_uring.c | 58 | ||||
| -rw-r--r-- | include/uapi/linux/io_uring.h | 10 |
2 files changed, 56 insertions, 12 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 86cbc024b0ecf..d2863ebd94ab8 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -894,6 +894,22 @@ struct io_defer_entry { u32 seq; }; +struct sqe_offset { + unsigned char user_data; + unsigned char personality; +}; + +static struct sqe_offset sqe_offsets[] = { + { + .user_data = offsetof(struct io_uring_sqe, user_data), + .personality = offsetof(struct io_uring_sqe, personality) + }, + { + .user_data = offsetof(struct io_uring_cmd_sqe, user_data), + .personality = offsetof(struct io_uring_cmd_sqe, personality) + } +}; + struct io_op_def { /* needs req->file assigned */ unsigned needs_file : 1; @@ -914,6 +930,8 @@ struct io_op_def { unsigned plug : 1; /* size of async data needed, if any */ unsigned short async_size; + /* offset definition for user_data/personality */ + unsigned short offsets; }; static const struct io_op_def io_op_defs[] = { @@ -1061,6 +1079,9 @@ static const struct io_op_def io_op_defs[] = { [IORING_OP_MKDIRAT] = {}, [IORING_OP_SYMLINKAT] = {}, [IORING_OP_LINKAT] = {}, + [IORING_OP_URING_CMD] = { + .offsets = 1, + }, }; static bool io_disarm_next(struct io_kiocb *req); @@ -6754,18 +6775,20 @@ static inline bool io_check_restriction(struct io_ring_ctx *ctx, } static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, - const struct io_uring_sqe *sqe) + const struct io_uring_sqe_hdr *hdr) __must_hold(&ctx->uring_lock) { struct io_submit_state *state; + const struct io_op_def *def; unsigned int sqe_flags; + const __u64 *uptr; + const __u16 *pptr; int personality, ret = 0; /* req is partially pre-initialised, see io_preinit_req() */ - req->opcode = READ_ONCE(sqe->hdr.opcode); + req->opcode = READ_ONCE(hdr->opcode); /* same numerical values with corresponding REQ_F_*, safe to copy */ - req->flags = sqe_flags = READ_ONCE(sqe->hdr.flags); - req->user_data = READ_ONCE(sqe->user_data); + req->flags = sqe_flags = READ_ONCE(hdr->flags); req->file = NULL; req->fixed_rsrc_refs = NULL; req->task = current; @@ -6778,13 +6801,17 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, if (!io_check_restriction(ctx, req, sqe_flags)) return -EACCES; - if ((sqe_flags & IOSQE_BUFFER_SELECT) && - !io_op_defs[req->opcode].buffer_select) + def = &io_op_defs[req->opcode]; + if ((sqe_flags & IOSQE_BUFFER_SELECT) && !def->buffer_select) return -EOPNOTSUPP; if (unlikely(sqe_flags & IOSQE_IO_DRAIN)) ctx->drain_active = true; - personality = READ_ONCE(sqe->personality); + uptr = (const void *) hdr + sqe_offsets[def->offsets].user_data; + req->user_data = READ_ONCE(*uptr); + + pptr = (const void *) hdr + sqe_offsets[def->offsets].personality; + personality = READ_ONCE(*pptr); if (personality) { req->creds = xa_load(&ctx->personalities, personality); if (!req->creds) @@ -6798,14 +6825,13 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, * Plug now if we have more than 1 IO left after this, and the target * is potentially a read/write to block based storage. */ - if (!state->plug_started && state->ios_left > 1 && - io_op_defs[req->opcode].plug) { + if (!state->plug_started && state->ios_left > 1 && def->plug) { blk_start_plug(&state->plug); state->plug_started = true; } - if (io_op_defs[req->opcode].needs_file) { - req->file = io_file_get(ctx, req, READ_ONCE(sqe->hdr.fd), + if (def->needs_file) { + req->file = io_file_get(ctx, req, READ_ONCE(hdr->fd), (sqe_flags & IOSQE_FIXED_FILE)); if (unlikely(!req->file)) ret = -EBADF; @@ -6822,7 +6848,7 @@ static int io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req, struct io_submit_link *link = &ctx->submit_state.link; int ret; - ret = io_init_req(ctx, req, sqe); + ret = io_init_req(ctx, req, &sqe->hdr); if (unlikely(ret)) { fail_req: if (link->head) { @@ -10467,6 +10493,7 @@ static int __init io_uring_init(void) #define BUILD_BUG_SQE_ELEM(eoffset, etype, ename) \ __BUILD_BUG_VERIFY_ELEMENT(struct io_uring_sqe, eoffset, etype, ename) BUILD_BUG_ON(sizeof(struct io_uring_sqe) != 64); + BUILD_BUG_ON(sizeof(struct io_uring_cmd_sqe) != 64); BUILD_BUG_SQE_ELEM(0, __u8, hdr.opcode); BUILD_BUG_SQE_ELEM(1, __u8, hdr.flags); BUILD_BUG_SQE_ELEM(2, __u16, hdr.ioprio); @@ -10497,6 +10524,13 @@ static int __init io_uring_init(void) BUILD_BUG_SQE_ELEM(42, __u16, personality); BUILD_BUG_SQE_ELEM(44, __s32, splice_fd_in); +#define BUILD_BUG_SQEC_ELEM(eoffset, etype, ename) \ + __BUILD_BUG_VERIFY_ELEMENT(struct io_uring_cmd_sqe, eoffset, etype, ename) + BUILD_BUG_SQEC_ELEM(8, __u64, user_data); + BUILD_BUG_SQEC_ELEM(18, __u16, personality); + BUILD_BUG_SQEC_ELEM(sqe_offsets[1].user_data, __u64, user_data); + BUILD_BUG_SQEC_ELEM(sqe_offsets[1].personality, __u16, personality); + BUILD_BUG_ON(sizeof(struct io_uring_files_update) != sizeof(struct io_uring_rsrc_update)); BUILD_BUG_ON(sizeof(struct io_uring_rsrc_update) > diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index 435d937b4a06d..eb25a137db4da 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -71,6 +71,15 @@ struct io_uring_sqe { __u64 __pad2[2]; }; +struct io_uring_cmd_sqe { + struct io_uring_sqe_hdr hdr; + __u64 user_data; + __u16 op; + __u16 personality; + __u32 len; + __u64 pdu[5]; +}; + enum { IOSQE_FIXED_FILE_BIT, IOSQE_IO_DRAIN_BIT, @@ -148,6 +157,7 @@ enum { IORING_OP_MKDIRAT, IORING_OP_SYMLINKAT, IORING_OP_LINKAT, + IORING_OP_URING_CMD, /* this goes last, obviously */ IORING_OP_LAST, |
