Update API

- io_uring_sqe added a data field that's passed back at completion
- io_uring_sqe added an index field, for fixed buffer locations
- io_uring_setup(2) system call added a 'nr_iovecs' field

Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Jens Axboe
2019-01-10 09:32:41 -07:00
parent 7bf7e8e8e5
commit 6cdce17753
6 changed files with 40 additions and 30 deletions

View File

@@ -189,11 +189,12 @@ err:
* contains the necessary information to read/write to the rings. * contains the necessary information to read/write to the rings.
*/ */
int io_uring_queue_init(unsigned entries, struct io_uring_params *p, int io_uring_queue_init(unsigned entries, struct io_uring_params *p,
struct iovec *iovecs, struct io_uring *ring) struct iovec *iovecs, unsigned nr_iovecs,
struct io_uring *ring)
{ {
int fd, ret; int fd, ret;
fd = io_uring_setup(entries, iovecs, p); fd = io_uring_setup(entries, iovecs, nr_iovecs, p);
if (fd < 0) if (fd < 0)
return fd; return fd;

View File

@@ -15,20 +15,23 @@
* IO submission data structure (Submission Queue Entry) * IO submission data structure (Submission Queue Entry)
*/ */
struct io_uring_sqe { struct io_uring_sqe {
__u8 opcode; __u8 opcode; /* type of operation for this sqe */
__u8 flags; __u8 flags; /* as of now unused */
__u16 ioprio; __u16 ioprio; /* ioprio for the request */
__s32 fd; __s32 fd; /* file descriptor to do IO on */
__u64 off; __u64 off; /* offset into file */
union { union {
void *addr; void *addr; /* buffer or iovecs */
__u64 __pad; __u64 __pad;
}; };
__u32 len; __u32 len; /* buffer size or number of iovecs */
union { union {
__kernel_rwf_t rw_flags; __kernel_rwf_t rw_flags;
__u32 __resv; __u32 __resv;
}; };
__u16 index; /* index into fixed buffers, if used */
__u16 __pad2[3];
__u64 data; /* data to be passed back at completion time */
}; };
/* /*
@@ -50,7 +53,7 @@ struct io_uring_sqe {
* IO completion data structure (Completion Queue Entry) * IO completion data structure (Completion Queue Entry)
*/ */
struct io_uring_cqe { struct io_uring_cqe {
__u64 index; /* what sqe this event came from */ __u64 data; /* sqe->data submission passed back */
__s32 res; /* result code for this event */ __s32 res; /* result code for this event */
__u32 flags; __u32 flags;
}; };

View File

@@ -44,7 +44,7 @@ struct io_uring {
* System calls * System calls
*/ */
extern int io_uring_setup(unsigned entries, struct iovec *iovecs, extern int io_uring_setup(unsigned entries, struct iovec *iovecs,
struct io_uring_params *p); unsigned nr_iovecs, struct io_uring_params *p);
extern int io_uring_enter(unsigned fd, unsigned to_submit, extern int io_uring_enter(unsigned fd, unsigned to_submit,
unsigned min_complete, unsigned flags); unsigned min_complete, unsigned flags);
@@ -52,7 +52,7 @@ extern int io_uring_enter(unsigned fd, unsigned to_submit,
* Library interface * Library interface
*/ */
extern int io_uring_queue_init(unsigned entries, struct io_uring_params *p, extern int io_uring_queue_init(unsigned entries, struct io_uring_params *p,
struct iovec *iovecs, struct io_uring *ring); struct iovec *iovecs, unsigned nr_iovecs, struct io_uring *ring);
extern void io_uring_queue_exit(struct io_uring *ring); extern void io_uring_queue_exit(struct io_uring *ring);
extern int io_uring_get_completion(struct io_uring *ring, extern int io_uring_get_completion(struct io_uring *ring,
struct io_uring_cqe **cqe_ptr); struct io_uring_cqe **cqe_ptr);
@@ -61,10 +61,4 @@ extern int io_uring_wait_completion(struct io_uring *ring,
extern int io_uring_submit(struct io_uring *ring); extern int io_uring_submit(struct io_uring *ring);
extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
static inline struct io_uring_sqe *
io_uring_sqe_from_cqe(struct io_uring *ring, struct io_uring_cqe *cqe)
{
return &ring->sq.sqes[cqe->index];
}
#endif #endif

View File

@@ -18,9 +18,9 @@
#endif #endif
int io_uring_setup(unsigned int entries, struct iovec *iovecs, int io_uring_setup(unsigned int entries, struct iovec *iovecs,
struct io_uring_params *p) unsigned nr_iovecs, struct io_uring_params *p)
{ {
return syscall(__NR_sys_io_uring_setup, entries, iovecs, p); return syscall(__NR_sys_io_uring_setup, entries, iovecs, nr_iovecs, p);
} }
int io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete, int io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete,

View File

@@ -18,6 +18,11 @@ static struct io_uring in_ring;
static struct io_uring out_ring; static struct io_uring out_ring;
static struct iovec iovecs[QD]; static struct iovec iovecs[QD];
struct io_data {
off_t offset;
struct iovec *iov;
};
static int setup_context(unsigned entries, struct io_uring *ring, int offload) static int setup_context(unsigned entries, struct io_uring *ring, int offload)
{ {
struct io_uring_params p; struct io_uring_params p;
@@ -27,7 +32,7 @@ static int setup_context(unsigned entries, struct io_uring *ring, int offload)
if (offload) if (offload)
p.flags = IORING_SETUP_SQWQ; p.flags = IORING_SETUP_SQWQ;
ret = io_uring_queue_init(entries, &p, NULL, ring); ret = io_uring_queue_init(entries, &p, NULL, 0, ring);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "queue_init: %s\n", strerror(-ret)); fprintf(stderr, "queue_init: %s\n", strerror(-ret));
return -1; return -1;
@@ -58,17 +63,23 @@ static unsigned sqe_index(struct io_uring_sqe *sqe)
static int queue_read(int fd, off_t size, off_t offset) static int queue_read(int fd, off_t size, off_t offset)
{ {
struct io_uring_sqe *sqe; struct io_uring_sqe *sqe;
struct io_data *data;
sqe = io_uring_get_sqe(&in_ring); sqe = io_uring_get_sqe(&in_ring);
if (!sqe) if (!sqe)
return 1; return 1;
data = malloc(sizeof(*data));
data->offset = offset;
data->iov = &iovecs[sqe_index(sqe)];
sqe->opcode = IORING_OP_READV; sqe->opcode = IORING_OP_READV;
sqe->flags = 0; sqe->flags = 0;
sqe->ioprio = 0; sqe->ioprio = 0;
sqe->fd = fd; sqe->fd = fd;
sqe->off = offset; sqe->off = offset;
sqe->addr = &iovecs[sqe_index(sqe)]; sqe->addr = data->iov;
sqe->data = (unsigned long) data;
iovecs[sqe_index(sqe)].iov_len = size; iovecs[sqe_index(sqe)].iov_len = size;
sqe->len = 1; sqe->len = 1;
return 0; return 0;
@@ -105,8 +116,9 @@ static int complete_writes(unsigned *writes)
return 0; return 0;
} }
static void queue_write(int fd, off_t size, off_t offset, unsigned index) static void queue_write(int fd, struct io_uring_cqe *cqe)
{ {
struct io_data *data = (struct io_data *) cqe->data;
struct io_uring_sqe *sqe; struct io_uring_sqe *sqe;
sqe = io_uring_get_sqe(&out_ring); sqe = io_uring_get_sqe(&out_ring);
@@ -114,10 +126,12 @@ static void queue_write(int fd, off_t size, off_t offset, unsigned index)
sqe->flags = 0; sqe->flags = 0;
sqe->ioprio = 0; sqe->ioprio = 0;
sqe->fd = fd; sqe->fd = fd;
sqe->off = offset; sqe->off = data->offset;
sqe->addr = &iovecs[index]; sqe->addr = data->iov;
iovecs[index].iov_len = size; sqe->data = 0;
data->iov->iov_len = cqe->res;
sqe->len = 1; sqe->len = 1;
free(data);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -164,7 +178,6 @@ int main(int argc, char *argv[])
write_left = read_left; write_left = read_left;
while (read_left || write_left) { while (read_left || write_left) {
off_t this_size = read_left; off_t this_size = read_left;
struct io_uring_sqe *sqe;
if (this_size > BS) if (this_size > BS)
this_size = BS; this_size = BS;
@@ -209,8 +222,7 @@ skip_read:
strerror(-cqe->res)); strerror(-cqe->res));
return 1; return 1;
} }
sqe = io_uring_sqe_from_cqe(&in_ring, cqe); queue_write(outfd, cqe);
queue_write(outfd, cqe->res, sqe->off, cqe->index);
write_left -= cqe->res; write_left -= cqe->res;
writes++; writes++;
}; };

View File

@@ -32,7 +32,7 @@ int main(int argc, char *argv[])
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));
p.flags = IORING_SETUP_IOPOLL; p.flags = IORING_SETUP_IOPOLL;
ret = io_uring_queue_init(QD, &p, NULL, &ring); ret = io_uring_queue_init(QD, &p, NULL, 0, &ring);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "queue_init: %s\n", strerror(-ret)); fprintf(stderr, "queue_init: %s\n", strerror(-ret));
return 1; return 1;