aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/io_uring/io_uring-cp.c21
-rw-r--r--tools/io_uring/liburing.h64
-rw-r--r--tools/io_uring/queue.c36
-rw-r--r--tools/io_uring/setup.c10
-rw-r--r--tools/io_uring/syscall.c48
5 files changed, 118 insertions, 61 deletions
diff --git a/tools/io_uring/io_uring-cp.c b/tools/io_uring/io_uring-cp.c
index 633f65bb43a7..81461813ec62 100644
--- a/tools/io_uring/io_uring-cp.c
+++ b/tools/io_uring/io_uring-cp.c
@@ -13,6 +13,7 @@
13#include <assert.h> 13#include <assert.h>
14#include <errno.h> 14#include <errno.h>
15#include <inttypes.h> 15#include <inttypes.h>
16#include <sys/types.h>
16#include <sys/stat.h> 17#include <sys/stat.h>
17#include <sys/ioctl.h> 18#include <sys/ioctl.h>
18 19
@@ -85,11 +86,16 @@ static int queue_read(struct io_uring *ring, off_t size, off_t offset)
85 struct io_uring_sqe *sqe; 86 struct io_uring_sqe *sqe;
86 struct io_data *data; 87 struct io_data *data;
87 88
89 data = malloc(size + sizeof(*data));
90 if (!data)
91 return 1;
92
88 sqe = io_uring_get_sqe(ring); 93 sqe = io_uring_get_sqe(ring);
89 if (!sqe) 94 if (!sqe) {
95 free(data);
90 return 1; 96 return 1;
97 }
91 98
92 data = malloc(size + sizeof(*data));
93 data->read = 1; 99 data->read = 1;
94 data->offset = data->first_offset = offset; 100 data->offset = data->first_offset = offset;
95 101
@@ -166,22 +172,23 @@ static int copy_file(struct io_uring *ring, off_t insize)
166 struct io_data *data; 172 struct io_data *data;
167 173
168 if (!got_comp) { 174 if (!got_comp) {
169 ret = io_uring_wait_completion(ring, &cqe); 175 ret = io_uring_wait_cqe(ring, &cqe);
170 got_comp = 1; 176 got_comp = 1;
171 } else 177 } else
172 ret = io_uring_get_completion(ring, &cqe); 178 ret = io_uring_peek_cqe(ring, &cqe);
173 if (ret < 0) { 179 if (ret < 0) {
174 fprintf(stderr, "io_uring_get_completion: %s\n", 180 fprintf(stderr, "io_uring_peek_cqe: %s\n",
175 strerror(-ret)); 181 strerror(-ret));
176 return 1; 182 return 1;
177 } 183 }
178 if (!cqe) 184 if (!cqe)
179 break; 185 break;
180 186
181 data = (struct io_data *) (uintptr_t) cqe->user_data; 187 data = io_uring_cqe_get_data(cqe);
182 if (cqe->res < 0) { 188 if (cqe->res < 0) {
183 if (cqe->res == -EAGAIN) { 189 if (cqe->res == -EAGAIN) {
184 queue_prepped(ring, data); 190 queue_prepped(ring, data);
191 io_uring_cqe_seen(ring, cqe);
185 continue; 192 continue;
186 } 193 }
187 fprintf(stderr, "cqe failed: %s\n", 194 fprintf(stderr, "cqe failed: %s\n",
@@ -193,6 +200,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
193 data->iov.iov_len -= cqe->res; 200 data->iov.iov_len -= cqe->res;
194 data->offset += cqe->res; 201 data->offset += cqe->res;
195 queue_prepped(ring, data); 202 queue_prepped(ring, data);
203 io_uring_cqe_seen(ring, cqe);
196 continue; 204 continue;
197 } 205 }
198 206
@@ -209,6 +217,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
209 free(data); 217 free(data);
210 writes--; 218 writes--;
211 } 219 }
220 io_uring_cqe_seen(ring, cqe);
212 } 221 }
213 } 222 }
214 223
diff --git a/tools/io_uring/liburing.h b/tools/io_uring/liburing.h
index cab0f50257ba..5f305c86b892 100644
--- a/tools/io_uring/liburing.h
+++ b/tools/io_uring/liburing.h
@@ -1,10 +1,16 @@
1#ifndef LIB_URING_H 1#ifndef LIB_URING_H
2#define LIB_URING_H 2#define LIB_URING_H
3 3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
4#include <sys/uio.h> 8#include <sys/uio.h>
5#include <signal.h> 9#include <signal.h>
6#include <string.h> 10#include <string.h>
7#include "../../include/uapi/linux/io_uring.h" 11#include "../../include/uapi/linux/io_uring.h"
12#include <inttypes.h>
13#include "barrier.h"
8 14
9/* 15/*
10 * Library interface to io_uring 16 * Library interface to io_uring
@@ -46,7 +52,7 @@ struct io_uring {
46 * System calls 52 * System calls
47 */ 53 */
48extern int io_uring_setup(unsigned entries, struct io_uring_params *p); 54extern int io_uring_setup(unsigned entries, struct io_uring_params *p);
49extern int io_uring_enter(unsigned fd, unsigned to_submit, 55extern int io_uring_enter(int fd, unsigned to_submit,
50 unsigned min_complete, unsigned flags, sigset_t *sig); 56 unsigned min_complete, unsigned flags, sigset_t *sig);
51extern int io_uring_register(int fd, unsigned int opcode, void *arg, 57extern int io_uring_register(int fd, unsigned int opcode, void *arg,
52 unsigned int nr_args); 58 unsigned int nr_args);
@@ -59,14 +65,33 @@ extern int io_uring_queue_init(unsigned entries, struct io_uring *ring,
59extern int io_uring_queue_mmap(int fd, struct io_uring_params *p, 65extern int io_uring_queue_mmap(int fd, struct io_uring_params *p,
60 struct io_uring *ring); 66 struct io_uring *ring);
61extern void io_uring_queue_exit(struct io_uring *ring); 67extern void io_uring_queue_exit(struct io_uring *ring);
62extern int io_uring_get_completion(struct io_uring *ring, 68extern int io_uring_peek_cqe(struct io_uring *ring,
63 struct io_uring_cqe **cqe_ptr); 69 struct io_uring_cqe **cqe_ptr);
64extern int io_uring_wait_completion(struct io_uring *ring, 70extern int io_uring_wait_cqe(struct io_uring *ring,
65 struct io_uring_cqe **cqe_ptr); 71 struct io_uring_cqe **cqe_ptr);
66extern int io_uring_submit(struct io_uring *ring); 72extern int io_uring_submit(struct io_uring *ring);
67extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); 73extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
68 74
69/* 75/*
76 * Must be called after io_uring_{peek,wait}_cqe() after the cqe has
77 * been processed by the application.
78 */
79static inline void io_uring_cqe_seen(struct io_uring *ring,
80 struct io_uring_cqe *cqe)
81{
82 if (cqe) {
83 struct io_uring_cq *cq = &ring->cq;
84
85 (*cq->khead)++;
86 /*
87 * Ensure that the kernel sees our new head, the kernel has
88 * the matching read barrier.
89 */
90 write_barrier();
91 }
92}
93
94/*
70 * Command prep helpers 95 * Command prep helpers
71 */ 96 */
72static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data) 97static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
@@ -74,8 +99,14 @@ static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
74 sqe->user_data = (unsigned long) data; 99 sqe->user_data = (unsigned long) data;
75} 100}
76 101
102static inline void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)
103{
104 return (void *) (uintptr_t) cqe->user_data;
105}
106
77static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, 107static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
78 void *addr, unsigned len, off_t offset) 108 const void *addr, unsigned len,
109 off_t offset)
79{ 110{
80 memset(sqe, 0, sizeof(*sqe)); 111 memset(sqe, 0, sizeof(*sqe));
81 sqe->opcode = op; 112 sqe->opcode = op;
@@ -86,8 +117,8 @@ static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
86} 117}
87 118
88static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd, 119static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd,
89 struct iovec *iovecs, unsigned nr_vecs, 120 const struct iovec *iovecs,
90 off_t offset) 121 unsigned nr_vecs, off_t offset)
91{ 122{
92 io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset); 123 io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset);
93} 124}
@@ -100,14 +131,14 @@ static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
100} 131}
101 132
102static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd, 133static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd,
103 struct iovec *iovecs, unsigned nr_vecs, 134 const struct iovec *iovecs,
104 off_t offset) 135 unsigned nr_vecs, off_t offset)
105{ 136{
106 io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset); 137 io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset);
107} 138}
108 139
109static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd, 140static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd,
110 void *buf, unsigned nbytes, 141 const void *buf, unsigned nbytes,
111 off_t offset) 142 off_t offset)
112{ 143{
113 io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset); 144 io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
@@ -131,13 +162,22 @@ static inline void io_uring_prep_poll_remove(struct io_uring_sqe *sqe,
131} 162}
132 163
133static inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd, 164static inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd,
134 int datasync) 165 unsigned fsync_flags)
135{ 166{
136 memset(sqe, 0, sizeof(*sqe)); 167 memset(sqe, 0, sizeof(*sqe));
137 sqe->opcode = IORING_OP_FSYNC; 168 sqe->opcode = IORING_OP_FSYNC;
138 sqe->fd = fd; 169 sqe->fd = fd;
139 if (datasync) 170 sqe->fsync_flags = fsync_flags;
140 sqe->fsync_flags = IORING_FSYNC_DATASYNC; 171}
172
173static inline void io_uring_prep_nop(struct io_uring_sqe *sqe)
174{
175 memset(sqe, 0, sizeof(*sqe));
176 sqe->opcode = IORING_OP_NOP;
177}
178
179#ifdef __cplusplus
141} 180}
181#endif
142 182
143#endif 183#endif
diff --git a/tools/io_uring/queue.c b/tools/io_uring/queue.c
index 88505e873ad9..321819c132c7 100644
--- a/tools/io_uring/queue.c
+++ b/tools/io_uring/queue.c
@@ -8,8 +8,8 @@
8#include "liburing.h" 8#include "liburing.h"
9#include "barrier.h" 9#include "barrier.h"
10 10
11static int __io_uring_get_completion(struct io_uring *ring, 11static int __io_uring_get_cqe(struct io_uring *ring,
12 struct io_uring_cqe **cqe_ptr, int wait) 12 struct io_uring_cqe **cqe_ptr, int wait)
13{ 13{
14 struct io_uring_cq *cq = &ring->cq; 14 struct io_uring_cq *cq = &ring->cq;
15 const unsigned mask = *cq->kring_mask; 15 const unsigned mask = *cq->kring_mask;
@@ -39,34 +39,25 @@ static int __io_uring_get_completion(struct io_uring *ring,
39 return -errno; 39 return -errno;
40 } while (1); 40 } while (1);
41 41
42 if (*cqe_ptr) {
43 *cq->khead = head + 1;
44 /*
45 * Ensure that the kernel sees our new head, the kernel has
46 * the matching read barrier.
47 */
48 write_barrier();
49 }
50
51 return 0; 42 return 0;
52} 43}
53 44
54/* 45/*
55 * Return an IO completion, if one is readily available 46 * Return an IO completion, if one is readily available. Returns 0 with
47 * cqe_ptr filled in on success, -errno on failure.
56 */ 48 */
57int io_uring_get_completion(struct io_uring *ring, 49int io_uring_peek_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr)
58 struct io_uring_cqe **cqe_ptr)
59{ 50{
60 return __io_uring_get_completion(ring, cqe_ptr, 0); 51 return __io_uring_get_cqe(ring, cqe_ptr, 0);
61} 52}
62 53
63/* 54/*
64 * Return an IO completion, waiting for it if necessary 55 * Return an IO completion, waiting for it if necessary. Returns 0 with
56 * cqe_ptr filled in on success, -errno on failure.
65 */ 57 */
66int io_uring_wait_completion(struct io_uring *ring, 58int io_uring_wait_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr)
67 struct io_uring_cqe **cqe_ptr)
68{ 59{
69 return __io_uring_get_completion(ring, cqe_ptr, 1); 60 return __io_uring_get_cqe(ring, cqe_ptr, 1);
70} 61}
71 62
72/* 63/*
@@ -78,7 +69,7 @@ int io_uring_submit(struct io_uring *ring)
78{ 69{
79 struct io_uring_sq *sq = &ring->sq; 70 struct io_uring_sq *sq = &ring->sq;
80 const unsigned mask = *sq->kring_mask; 71 const unsigned mask = *sq->kring_mask;
81 unsigned ktail, ktail_next, submitted; 72 unsigned ktail, ktail_next, submitted, to_submit;
82 int ret; 73 int ret;
83 74
84 /* 75 /*
@@ -100,7 +91,8 @@ int io_uring_submit(struct io_uring *ring)
100 */ 91 */
101 submitted = 0; 92 submitted = 0;
102 ktail = ktail_next = *sq->ktail; 93 ktail = ktail_next = *sq->ktail;
103 while (sq->sqe_head < sq->sqe_tail) { 94 to_submit = sq->sqe_tail - sq->sqe_head;
95 while (to_submit--) {
104 ktail_next++; 96 ktail_next++;
105 read_barrier(); 97 read_barrier();
106 98
@@ -136,7 +128,7 @@ submit:
136 if (ret < 0) 128 if (ret < 0)
137 return -errno; 129 return -errno;
138 130
139 return 0; 131 return ret;
140} 132}
141 133
142/* 134/*
diff --git a/tools/io_uring/setup.c b/tools/io_uring/setup.c
index 4da19a77132c..0b50fcd78520 100644
--- a/tools/io_uring/setup.c
+++ b/tools/io_uring/setup.c
@@ -27,7 +27,7 @@ static int io_uring_mmap(int fd, struct io_uring_params *p,
27 sq->kdropped = ptr + p->sq_off.dropped; 27 sq->kdropped = ptr + p->sq_off.dropped;
28 sq->array = ptr + p->sq_off.array; 28 sq->array = ptr + p->sq_off.array;
29 29
30 size = p->sq_entries * sizeof(struct io_uring_sqe), 30 size = p->sq_entries * sizeof(struct io_uring_sqe);
31 sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE, 31 sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE,
32 MAP_SHARED | MAP_POPULATE, fd, 32 MAP_SHARED | MAP_POPULATE, fd,
33 IORING_OFF_SQES); 33 IORING_OFF_SQES);
@@ -79,7 +79,7 @@ int io_uring_queue_mmap(int fd, struct io_uring_params *p, struct io_uring *ring
79int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags) 79int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags)
80{ 80{
81 struct io_uring_params p; 81 struct io_uring_params p;
82 int fd; 82 int fd, ret;
83 83
84 memset(&p, 0, sizeof(p)); 84 memset(&p, 0, sizeof(p));
85 p.flags = flags; 85 p.flags = flags;
@@ -88,7 +88,11 @@ int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags)
88 if (fd < 0) 88 if (fd < 0)
89 return fd; 89 return fd;
90 90
91 return io_uring_queue_mmap(fd, &p, ring); 91 ret = io_uring_queue_mmap(fd, &p, ring);
92 if (ret)
93 close(fd);
94
95 return ret;
92} 96}
93 97
94void io_uring_queue_exit(struct io_uring *ring) 98void io_uring_queue_exit(struct io_uring *ring)
diff --git a/tools/io_uring/syscall.c b/tools/io_uring/syscall.c
index 6b835e5c6a5b..b22e0aa54e9d 100644
--- a/tools/io_uring/syscall.c
+++ b/tools/io_uring/syscall.c
@@ -7,34 +7,46 @@
7#include <signal.h> 7#include <signal.h>
8#include "liburing.h" 8#include "liburing.h"
9 9
10#if defined(__x86_64) || defined(__i386__) 10#ifdef __alpha__
11#ifndef __NR_sys_io_uring_setup 11/*
12#define __NR_sys_io_uring_setup 425 12 * alpha is the only exception, all other architectures
13#endif 13 * have common numbers for new system calls.
14#ifndef __NR_sys_io_uring_enter 14 */
15#define __NR_sys_io_uring_enter 426 15# ifndef __NR_io_uring_setup
16#endif 16# define __NR_io_uring_setup 535
17#ifndef __NR_sys_io_uring_register 17# endif
18#define __NR_sys_io_uring_register 427 18# ifndef __NR_io_uring_enter
19#endif 19# define __NR_io_uring_enter 536
20#else 20# endif
21#error "Arch not supported yet" 21# ifndef __NR_io_uring_register
22# define __NR_io_uring_register 537
23# endif
24#else /* !__alpha__ */
25# ifndef __NR_io_uring_setup
26# define __NR_io_uring_setup 425
27# endif
28# ifndef __NR_io_uring_enter
29# define __NR_io_uring_enter 426
30# endif
31# ifndef __NR_io_uring_register
32# define __NR_io_uring_register 427
33# endif
22#endif 34#endif
23 35
24int io_uring_register(int fd, unsigned int opcode, void *arg, 36int io_uring_register(int fd, unsigned int opcode, void *arg,
25 unsigned int nr_args) 37 unsigned int nr_args)
26{ 38{
27 return syscall(__NR_sys_io_uring_register, fd, opcode, arg, nr_args); 39 return syscall(__NR_io_uring_register, fd, opcode, arg, nr_args);
28} 40}
29 41
30int io_uring_setup(unsigned entries, struct io_uring_params *p) 42int io_uring_setup(unsigned int entries, struct io_uring_params *p)
31{ 43{
32 return syscall(__NR_sys_io_uring_setup, entries, p); 44 return syscall(__NR_io_uring_setup, entries, p);
33} 45}
34 46
35int io_uring_enter(unsigned fd, unsigned to_submit, unsigned min_complete, 47int io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete,
36 unsigned flags, sigset_t *sig) 48 unsigned int flags, sigset_t *sig)
37{ 49{
38 return syscall(__NR_sys_io_uring_enter, fd, to_submit, min_complete, 50 return syscall(__NR_io_uring_enter, fd, to_submit, min_complete,
39 flags, sig, _NSIG / 8); 51 flags, sig, _NSIG / 8);
40} 52}