Skip to content

Commit 004d564

Browse files
committed
tools/io_uring: sync with liburing
Various fixes and changes have been applied to liburing since we copied some select bits to the kernel testing/examples part, sync up with liburing to get those changes. Most notable is the change that split the CQE reading into the peek and seen event, instead of being just a single function. Also fixes an unsigned wrap issue in io_uring_submit(), leak of 'fd' in setup if we fail, and various other little issues. Signed-off-by: Jens Axboe <[email protected]>
1 parent 486f069 commit 004d564

File tree

5 files changed

+118
-61
lines changed

5 files changed

+118
-61
lines changed

tools/io_uring/io_uring-cp.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <assert.h>
1414
#include <errno.h>
1515
#include <inttypes.h>
16+
#include <sys/types.h>
1617
#include <sys/stat.h>
1718
#include <sys/ioctl.h>
1819

@@ -85,11 +86,16 @@ static int queue_read(struct io_uring *ring, off_t size, off_t offset)
8586
struct io_uring_sqe *sqe;
8687
struct io_data *data;
8788

89+
data = malloc(size + sizeof(*data));
90+
if (!data)
91+
return 1;
92+
8893
sqe = io_uring_get_sqe(ring);
89-
if (!sqe)
94+
if (!sqe) {
95+
free(data);
9096
return 1;
97+
}
9198

92-
data = malloc(size + sizeof(*data));
9399
data->read = 1;
94100
data->offset = data->first_offset = offset;
95101

@@ -166,22 +172,23 @@ static int copy_file(struct io_uring *ring, off_t insize)
166172
struct io_data *data;
167173

168174
if (!got_comp) {
169-
ret = io_uring_wait_completion(ring, &cqe);
175+
ret = io_uring_wait_cqe(ring, &cqe);
170176
got_comp = 1;
171177
} else
172-
ret = io_uring_get_completion(ring, &cqe);
178+
ret = io_uring_peek_cqe(ring, &cqe);
173179
if (ret < 0) {
174-
fprintf(stderr, "io_uring_get_completion: %s\n",
180+
fprintf(stderr, "io_uring_peek_cqe: %s\n",
175181
strerror(-ret));
176182
return 1;
177183
}
178184
if (!cqe)
179185
break;
180186

181-
data = (struct io_data *) (uintptr_t) cqe->user_data;
187+
data = io_uring_cqe_get_data(cqe);
182188
if (cqe->res < 0) {
183189
if (cqe->res == -EAGAIN) {
184190
queue_prepped(ring, data);
191+
io_uring_cqe_seen(ring, cqe);
185192
continue;
186193
}
187194
fprintf(stderr, "cqe failed: %s\n",
@@ -193,6 +200,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
193200
data->iov.iov_len -= cqe->res;
194201
data->offset += cqe->res;
195202
queue_prepped(ring, data);
203+
io_uring_cqe_seen(ring, cqe);
196204
continue;
197205
}
198206

@@ -209,6 +217,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
209217
free(data);
210218
writes--;
211219
}
220+
io_uring_cqe_seen(ring, cqe);
212221
}
213222
}
214223

tools/io_uring/liburing.h

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
#ifndef LIB_URING_H
22
#define LIB_URING_H
33

4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
48
#include <sys/uio.h>
59
#include <signal.h>
610
#include <string.h>
711
#include "../../include/uapi/linux/io_uring.h"
12+
#include <inttypes.h>
13+
#include "barrier.h"
814

915
/*
1016
* Library interface to io_uring
@@ -46,7 +52,7 @@ struct io_uring {
4652
* System calls
4753
*/
4854
extern int io_uring_setup(unsigned entries, struct io_uring_params *p);
49-
extern int io_uring_enter(unsigned fd, unsigned to_submit,
55+
extern int io_uring_enter(int fd, unsigned to_submit,
5056
unsigned min_complete, unsigned flags, sigset_t *sig);
5157
extern int io_uring_register(int fd, unsigned int opcode, void *arg,
5258
unsigned int nr_args);
@@ -59,13 +65,32 @@ extern int io_uring_queue_init(unsigned entries, struct io_uring *ring,
5965
extern int io_uring_queue_mmap(int fd, struct io_uring_params *p,
6066
struct io_uring *ring);
6167
extern void io_uring_queue_exit(struct io_uring *ring);
62-
extern int io_uring_get_completion(struct io_uring *ring,
68+
extern int io_uring_peek_cqe(struct io_uring *ring,
6369
struct io_uring_cqe **cqe_ptr);
64-
extern int io_uring_wait_completion(struct io_uring *ring,
70+
extern int io_uring_wait_cqe(struct io_uring *ring,
6571
struct io_uring_cqe **cqe_ptr);
6672
extern int io_uring_submit(struct io_uring *ring);
6773
extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
6874

75+
/*
76+
* Must be called after io_uring_{peek,wait}_cqe() after the cqe has
77+
* been processed by the application.
78+
*/
79+
static 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+
6994
/*
7095
* Command prep helpers
7196
*/
@@ -74,8 +99,14 @@ static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
7499
sqe->user_data = (unsigned long) data;
75100
}
76101

102+
static inline void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)
103+
{
104+
return (void *) (uintptr_t) cqe->user_data;
105+
}
106+
77107
static 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)
79110
{
80111
memset(sqe, 0, sizeof(*sqe));
81112
sqe->opcode = op;
@@ -86,8 +117,8 @@ static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
86117
}
87118

88119
static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd,
89-
struct iovec *iovecs, unsigned nr_vecs,
90-
off_t offset)
120+
const struct iovec *iovecs,
121+
unsigned nr_vecs, off_t offset)
91122
{
92123
io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset);
93124
}
@@ -100,14 +131,14 @@ static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
100131
}
101132

102133
static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd,
103-
struct iovec *iovecs, unsigned nr_vecs,
104-
off_t offset)
134+
const struct iovec *iovecs,
135+
unsigned nr_vecs, off_t offset)
105136
{
106137
io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset);
107138
}
108139

109140
static 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,
111142
off_t offset)
112143
{
113144
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,
131162
}
132163

133164
static inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd,
134-
int datasync)
165+
unsigned fsync_flags)
135166
{
136167
memset(sqe, 0, sizeof(*sqe));
137168
sqe->opcode = IORING_OP_FSYNC;
138169
sqe->fd = fd;
139-
if (datasync)
140-
sqe->fsync_flags = IORING_FSYNC_DATASYNC;
170+
sqe->fsync_flags = fsync_flags;
171+
}
172+
173+
static 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
141180
}
181+
#endif
142182

143183
#endif

tools/io_uring/queue.c

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#include "liburing.h"
99
#include "barrier.h"
1010

11-
static int __io_uring_get_completion(struct io_uring *ring,
12-
struct io_uring_cqe **cqe_ptr, int wait)
11+
static int __io_uring_get_cqe(struct io_uring *ring,
12+
struct io_uring_cqe **cqe_ptr, int wait)
1313
{
1414
struct io_uring_cq *cq = &ring->cq;
1515
const unsigned mask = *cq->kring_mask;
@@ -39,34 +39,25 @@ static int __io_uring_get_completion(struct io_uring *ring,
3939
return -errno;
4040
} while (1);
4141

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-
5142
return 0;
5243
}
5344

5445
/*
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.
5648
*/
57-
int io_uring_get_completion(struct io_uring *ring,
58-
struct io_uring_cqe **cqe_ptr)
49+
int io_uring_peek_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr)
5950
{
60-
return __io_uring_get_completion(ring, cqe_ptr, 0);
51+
return __io_uring_get_cqe(ring, cqe_ptr, 0);
6152
}
6253

6354
/*
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.
6557
*/
66-
int io_uring_wait_completion(struct io_uring *ring,
67-
struct io_uring_cqe **cqe_ptr)
58+
int io_uring_wait_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr)
6859
{
69-
return __io_uring_get_completion(ring, cqe_ptr, 1);
60+
return __io_uring_get_cqe(ring, cqe_ptr, 1);
7061
}
7162

7263
/*
@@ -78,7 +69,7 @@ int io_uring_submit(struct io_uring *ring)
7869
{
7970
struct io_uring_sq *sq = &ring->sq;
8071
const unsigned mask = *sq->kring_mask;
81-
unsigned ktail, ktail_next, submitted;
72+
unsigned ktail, ktail_next, submitted, to_submit;
8273
int ret;
8374

8475
/*
@@ -100,7 +91,8 @@ int io_uring_submit(struct io_uring *ring)
10091
*/
10192
submitted = 0;
10293
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--) {
10496
ktail_next++;
10597
read_barrier();
10698

@@ -136,7 +128,7 @@ int io_uring_submit(struct io_uring *ring)
136128
if (ret < 0)
137129
return -errno;
138130

139-
return 0;
131+
return ret;
140132
}
141133

142134
/*

tools/io_uring/setup.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static int io_uring_mmap(int fd, struct io_uring_params *p,
2727
sq->kdropped = ptr + p->sq_off.dropped;
2828
sq->array = ptr + p->sq_off.array;
2929

30-
size = p->sq_entries * sizeof(struct io_uring_sqe),
30+
size = p->sq_entries * sizeof(struct io_uring_sqe);
3131
sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE,
3232
MAP_SHARED | MAP_POPULATE, fd,
3333
IORING_OFF_SQES);
@@ -79,7 +79,7 @@ int io_uring_queue_mmap(int fd, struct io_uring_params *p, struct io_uring *ring
7979
int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags)
8080
{
8181
struct io_uring_params p;
82-
int fd;
82+
int fd, ret;
8383

8484
memset(&p, 0, sizeof(p));
8585
p.flags = flags;
@@ -88,7 +88,11 @@ int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags)
8888
if (fd < 0)
8989
return fd;
9090

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;
9296
}
9397

9498
void io_uring_queue_exit(struct io_uring *ring)

tools/io_uring/syscall.c

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,46 @@
77
#include <signal.h>
88
#include "liburing.h"
99

10-
#if defined(__x86_64) || defined(__i386__)
11-
#ifndef __NR_sys_io_uring_setup
12-
#define __NR_sys_io_uring_setup 425
13-
#endif
14-
#ifndef __NR_sys_io_uring_enter
15-
#define __NR_sys_io_uring_enter 426
16-
#endif
17-
#ifndef __NR_sys_io_uring_register
18-
#define __NR_sys_io_uring_register 427
19-
#endif
20-
#else
21-
#error "Arch not supported yet"
10+
#ifdef __alpha__
11+
/*
12+
* alpha is the only exception, all other architectures
13+
* have common numbers for new system calls.
14+
*/
15+
# ifndef __NR_io_uring_setup
16+
# define __NR_io_uring_setup 535
17+
# endif
18+
# ifndef __NR_io_uring_enter
19+
# define __NR_io_uring_enter 536
20+
# endif
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
2234
#endif
2335

2436
int io_uring_register(int fd, unsigned int opcode, void *arg,
2537
unsigned int nr_args)
2638
{
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);
2840
}
2941

30-
int io_uring_setup(unsigned entries, struct io_uring_params *p)
42+
int io_uring_setup(unsigned int entries, struct io_uring_params *p)
3143
{
32-
return syscall(__NR_sys_io_uring_setup, entries, p);
44+
return syscall(__NR_io_uring_setup, entries, p);
3345
}
3446

35-
int io_uring_enter(unsigned fd, unsigned to_submit, unsigned min_complete,
36-
unsigned flags, sigset_t *sig)
47+
int io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete,
48+
unsigned int flags, sigset_t *sig)
3749
{
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,
3951
flags, sig, _NSIG / 8);
4052
}

0 commit comments

Comments
 (0)