aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2021-03-17 12:12:46 -0600
committerJens Axboe <axboe@kernel.dk>2021-07-12 11:29:12 -0600
commit927dd9f4caa6914a774d26dc2ed922a26966a656 (patch)
tree3febab77220cfa81e968dec1d6b609cabf2eed01
parente48962add6770d28aaaf9e2f8218173a238650f5 (diff)
downloadlinux-block-927dd9f4caa6914a774d26dc2ed922a26966a656.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.c59
-rw-r--r--include/uapi/linux/io_uring.h10
2 files changed, 56 insertions, 13 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 421c89831cf6e..ad6d5f6770a78 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -878,6 +878,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;
@@ -898,6 +914,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[] = {
@@ -1042,6 +1060,9 @@ static const struct io_op_def io_op_defs[] = {
},
[IORING_OP_RENAMEAT] = {},
[IORING_OP_UNLINKAT] = {},
+ [IORING_OP_URING_CMD] = {
+ .offsets = 1,
+ },
};
static bool io_disarm_next(struct io_kiocb *req);
@@ -6499,16 +6520,18 @@ 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)
{
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->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;
/* one is dropped after submission, the other at completion */
@@ -6523,13 +6546,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)
@@ -6543,17 +6570,15 @@ 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) {
+ if (def->needs_file) {
bool fixed = req->flags & REQ_F_FIXED_FILE;
- req->file = io_file_get(state, req, READ_ONCE(sqe->hdr.fd),
- fixed);
+ req->file = io_file_get(state, req, READ_ONCE(hdr->fd), fixed);
if (unlikely(!req->file))
ret = -EBADF;
}
@@ -6568,7 +6593,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) {
@@ -10216,6 +10241,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);
@@ -10246,6 +10272,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 c372cc36da1a8..92565e17bfd93 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -70,6 +70,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,
@@ -144,6 +153,7 @@ enum {
IORING_OP_SHUTDOWN,
IORING_OP_RENAMEAT,
IORING_OP_UNLINKAT,
+ IORING_OP_URING_CMD,
/* this goes last, obviously */
IORING_OP_LAST,