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:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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++;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user